using System; using System.Threading.Tasks; using FluentAssertions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using TeleBot.Services; using Xunit; namespace TeleBot.Tests.Services { public class PrivacyServiceTests { private readonly PrivacyService _privacyService; private readonly Mock _mockConfiguration; private readonly Mock> _mockLogger; public PrivacyServiceTests() { _mockConfiguration = new Mock(); _mockLogger = new Mock>(); // Set up default configuration _mockConfiguration.Setup(x => x["Privacy:HashSalt"]) .Returns("TestSalt123"); _mockConfiguration.Setup(x => x["Privacy:EnableTor"]) .Returns("false"); _privacyService = new PrivacyService(_mockConfiguration.Object, _mockLogger.Object); } [Fact] public void HashIdentifier_ShouldReturnConsistentHash() { // Arrange long telegramId = 123456789; // Act var hash1 = _privacyService.HashIdentifier(telegramId); var hash2 = _privacyService.HashIdentifier(telegramId); // Assert hash1.Should().NotBeNullOrEmpty(); hash2.Should().NotBeNullOrEmpty(); hash1.Should().Be(hash2, "Hash should be consistent for the same input"); } [Fact] public void HashIdentifier_DifferentIds_ShouldReturnDifferentHashes() { // Arrange long telegramId1 = 123456789; long telegramId2 = 987654321; // Act var hash1 = _privacyService.HashIdentifier(telegramId1); var hash2 = _privacyService.HashIdentifier(telegramId2); // Assert hash1.Should().NotBe(hash2, "Different IDs should produce different hashes"); } [Fact] public void GenerateAnonymousReference_ShouldReturnUniqueReferences() { // Act var ref1 = _privacyService.GenerateAnonymousReference(); var ref2 = _privacyService.GenerateAnonymousReference(); // Assert ref1.Should().StartWith("ANON-"); ref2.Should().StartWith("ANON-"); ref1.Should().HaveLength(17); // ANON- (5) + 12 characters ref1.Should().NotBe(ref2, "Each reference should be unique"); } [Fact] public void GenerateAnonymousReference_ShouldNotContainSpecialCharacters() { // Act var reference = _privacyService.GenerateAnonymousReference(); // Assert reference.Should().MatchRegex(@"^ANON-[A-Z0-9]+$"); } [Fact] public async Task CreateTorHttpClient_WhenTorDisabled_ShouldReturnRegularClient() { // Arrange _mockConfiguration.Setup(x => x["Privacy:EnableTor"]) .Returns("false"); // Act var client = await _privacyService.CreateTorHttpClient(); // Assert client.Should().NotBeNull(); client.Timeout.Should().Be(TimeSpan.FromSeconds(100)); // Default timeout } [Fact] public void EncryptData_ShouldEncryptAndDecryptSuccessfully() { // Arrange var originalData = System.Text.Encoding.UTF8.GetBytes("Secret message"); var key = "TestEncryptionKey123"; // Act var encrypted = _privacyService.EncryptData(originalData, key); var decrypted = _privacyService.DecryptData(encrypted, key); // Assert encrypted.Should().NotBeEquivalentTo(originalData, "Data should be encrypted"); decrypted.Should().BeEquivalentTo(originalData, "Decrypted data should match original"); } [Fact] public void EncryptData_WithDifferentKeys_ShouldProduceDifferentResults() { // Arrange var originalData = System.Text.Encoding.UTF8.GetBytes("Secret message"); var key1 = "Key1"; var key2 = "Key2"; // Act var encrypted1 = _privacyService.EncryptData(originalData, key1); var encrypted2 = _privacyService.EncryptData(originalData, key2); // Assert encrypted1.Should().NotBeEquivalentTo(encrypted2, "Different keys should produce different encryptions"); } [Fact] public void SanitizeLogMessage_ShouldRemoveEmail() { // Arrange var message = "User email is test@example.com in the system"; // Act _privacyService.SanitizeLogMessage(ref message); // Assert message.Should().Be("User email is [EMAIL_REDACTED] in the system"); } [Fact] public void SanitizeLogMessage_ShouldRemovePhoneNumber() { // Arrange var message = "Contact number: 555-123-4567"; // Act _privacyService.SanitizeLogMessage(ref message); // Assert message.Should().Be("Contact number: [PHONE_REDACTED]"); } [Fact] public void SanitizeLogMessage_ShouldRemoveTelegramId() { // Arrange var message = "Processing request for telegram_id:123456789"; // Act _privacyService.SanitizeLogMessage(ref message); // Assert message.Should().Be("Processing request for telegram_id=[REDACTED]"); } [Theory] [InlineData("")] [InlineData("Normal log message without PII")] [InlineData("Order ID: 12345")] public void SanitizeLogMessage_WithoutPII_ShouldRemainUnchanged(string message) { // Arrange var original = message; // Act _privacyService.SanitizeLogMessage(ref message); // Assert message.Should().Be(original); } } }