using ColaFlow.Modules.Mcp.Infrastructure.Auditing;
using ColaFlow.Modules.Mcp.Infrastructure.Reporting;
using ColaFlow.Modules.Mcp.Infrastructure.Validation;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Moq;
namespace ColaFlow.IntegrationTests.Mcp;
///
/// Tests for multi-tenant security report generation
///
public class MultiTenantSecurityReportTests
{
[Fact]
public void SecurityReport_IsGenerated_Successfully()
{
// Arrange
var mockLogger = new Mock>();
var auditLogger = new McpSecurityAuditLogger(mockLogger.Object);
var mockValidatorLogger = new Mock>();
var tenantValidator = new TenantContextValidator(mockValidatorLogger.Object);
var reportGenerator = new MultiTenantSecurityReportGenerator(auditLogger, tenantValidator);
// Act
var report = reportGenerator.GenerateReport();
// Assert
report.Should().NotBeNull();
report.GeneratedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5));
report.SecurityChecks.Should().NotBeNull();
report.AuditStatistics.Should().NotBeNull();
report.ValidationStatistics.Should().NotBeNull();
report.OverallScore.Should().NotBeNull();
}
[Fact]
public void SecurityReport_TextFormat_ContainsRequiredSections()
{
// Arrange
var reportGenerator = new MultiTenantSecurityReportGenerator();
// Act
var textReport = reportGenerator.GenerateTextReport();
// Assert
textReport.Should().Contain("MULTI-TENANT SECURITY VERIFICATION REPORT");
textReport.Should().Contain("OVERALL SECURITY SCORE");
textReport.Should().Contain("SECURITY CHECKS");
textReport.Should().Contain("AUDIT STATISTICS");
textReport.Should().Contain("QUERY VALIDATION STATISTICS");
}
[Fact]
public void SecurityReport_MarkdownFormat_ContainsRequiredSections()
{
// Arrange
var reportGenerator = new MultiTenantSecurityReportGenerator();
// Act
var markdownReport = reportGenerator.GenerateMarkdownReport();
// Assert
markdownReport.Should().Contain("# Multi-Tenant Security Verification Report");
markdownReport.Should().Contain("## Overall Security Score");
markdownReport.Should().Contain("## Security Checks");
markdownReport.Should().Contain("## Audit Statistics");
}
[Fact]
public void SecurityScore_IsCalculated_Correctly()
{
// Arrange
var reportGenerator = new MultiTenantSecurityReportGenerator();
// Act
var report = reportGenerator.GenerateReport();
// Assert
report.OverallScore.Score.Should().BeGreaterThanOrEqualTo(0);
report.OverallScore.Score.Should().BeLessThanOrEqualTo(100);
report.OverallScore.Grade.Should().NotBeNullOrEmpty();
report.OverallScore.Status.Should().NotBeNullOrEmpty();
}
[Fact]
public void SecurityChecks_AllPass_WhenNoIssues()
{
// Arrange
var reportGenerator = new MultiTenantSecurityReportGenerator();
// Act
var report = reportGenerator.GenerateReport();
// Assert
report.SecurityChecks.TotalChecks.Should().BeGreaterThan(0);
report.SecurityChecks.PassedChecks.Should().BeGreaterThanOrEqualTo(0);
report.SecurityChecks.FailedChecks.Should().BeGreaterThanOrEqualTo(0);
(report.SecurityChecks.PassedChecks + report.SecurityChecks.FailedChecks)
.Should().Be(report.SecurityChecks.TotalChecks);
}
[Fact]
public void AuditLogger_RecordsSuccess_Correctly()
{
// Arrange
var mockLogger = new Mock>();
var auditLogger = new McpSecurityAuditLogger(mockLogger.Object);
var auditEvent = new McpSecurityAuditEvent
{
TenantId = Guid.NewGuid(),
UserId = Guid.NewGuid(),
Operation = "test_operation",
Success = true
};
// Act
auditLogger.LogSuccess(auditEvent);
var stats = auditLogger.GetAuditStatistics();
// Assert
stats.TotalOperations.Should().Be(1);
stats.SuccessfulOperations.Should().Be(1);
stats.FailedOperations.Should().Be(0);
}
[Fact]
public void AuditLogger_RecordsCrossTenantAttempt_Correctly()
{
// Arrange
var mockLogger = new Mock>();
var auditLogger = new McpSecurityAuditLogger(mockLogger.Object);
var auditEvent = new McpSecurityAuditEvent
{
TenantId = Guid.NewGuid(),
TargetTenantId = Guid.NewGuid(),
UserId = Guid.NewGuid(),
Operation = "cross_tenant_access",
ResourceType = "projects",
ResourceId = Guid.NewGuid()
};
// Act
auditLogger.LogCrossTenantAccessAttempt(auditEvent);
var stats = auditLogger.GetAuditStatistics();
// Assert
stats.CrossTenantAccessAttempts.Should().Be(1);
stats.FailedOperations.Should().Be(1);
stats.LastCrossTenantAttempt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5));
}
[Fact]
public void TenantValidator_DetectsQueryWithTenantFilter()
{
// Arrange
var mockLogger = new Mock>();
var validator = new TenantContextValidator(mockLogger.Object);
var queryWithFilter = "SELECT * FROM Projects WHERE TenantId = @tenantId";
// Act
var result = validator.ValidateQueryIncludesTenantFilter(queryWithFilter);
var stats = validator.GetValidationStats();
// Assert
result.Should().BeTrue();
stats.QueriesWithTenantFilter.Should().Be(1);
stats.QueriesWithoutTenantFilter.Should().Be(0);
}
[Fact]
public void TenantValidator_DetectsQueryWithoutTenantFilter()
{
// Arrange
var mockLogger = new Mock>();
var validator = new TenantContextValidator(mockLogger.Object);
var queryWithoutFilter = "SELECT * FROM Projects WHERE Name = 'Test'";
// Act
var result = validator.ValidateQueryIncludesTenantFilter(queryWithoutFilter);
var stats = validator.GetValidationStats();
// Assert
result.Should().BeFalse();
stats.QueriesWithTenantFilter.Should().Be(0);
stats.QueriesWithoutTenantFilter.Should().Be(1);
stats.ViolatingQueries.Should().Contain(queryWithoutFilter);
}
[Fact]
public void SecurityReport_IncludesFindings_ForCrossTenantAttempts()
{
// Arrange
var mockLogger = new Mock>();
var auditLogger = new McpSecurityAuditLogger(mockLogger.Object);
// Log a cross-tenant access attempt
auditLogger.LogCrossTenantAccessAttempt(new McpSecurityAuditEvent
{
TenantId = Guid.NewGuid(),
TargetTenantId = Guid.NewGuid()
});
var reportGenerator = new MultiTenantSecurityReportGenerator(auditLogger);
// Act
var report = reportGenerator.GenerateReport();
// Assert
report.Findings.Should().NotBeEmpty();
report.Findings.Should().Contain(f => f.Category.Contains("Cross-Tenant Access"));
}
[Fact]
public void SecurityReport_IncludesFindings_ForUnfilteredQueries()
{
// Arrange
var mockValidatorLogger = new Mock>();
var validator = new TenantContextValidator(mockValidatorLogger.Object);
// Validate a query without tenant filter
validator.ValidateQueryIncludesTenantFilter("SELECT * FROM Projects");
var reportGenerator = new MultiTenantSecurityReportGenerator(tenantValidator: validator);
// Act
var report = reportGenerator.GenerateReport();
// Assert
report.Findings.Should().NotBeEmpty();
report.Findings.Should().Contain(f => f.Category.Contains("Queries Without TenantId Filter"));
report.Findings.Should().Contain(f => f.Severity == "Critical");
}
[Fact]
public void SecurityReport_ShowsPerfectScore_WhenNoIssues()
{
// Arrange
var reportGenerator = new MultiTenantSecurityReportGenerator();
// Act
var report = reportGenerator.GenerateReport();
// Assert - With no issues, should have high score
report.OverallScore.Score.Should().BeGreaterThanOrEqualTo(90);
report.OverallScore.Status.Should().BeOneOf("Pass", "Warning");
}
}