/* * Copyright (c) 2025 Proton AG * * This file is part of ProtonVPN. * * ProtonVPN is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ProtonVPN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ProtonVPN. If not, see . */ using FluentAssertions; using ProtonVPN.IssueReporting.DataScrubbing; namespace ProtonVPN.IssueReporting.Tests; [TestClass] public class SentryEventScrubberProcessorTests { private SentryEventScrubberProcessor _processor; [TestInitialize] public void TestInitialize() { _processor = new SentryEventScrubberProcessor(); } [TestMethod] public void Process_ShouldScrubEmailInMessage() { // Arrange SentryEvent sentryEvent = new() { Message = "User john.doe@example.com encountered an error" }; // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Message.Message.Should().NotContain("john.doe@example.com"); result.Message.Message.Should().Contain("[REDACTED_EMAIL]"); } [TestMethod] public void Process_ShouldScrubUserPathInMessage() { // Arrange SentryEvent sentryEvent = new() { Message = @"Error at C:\Users\JohnDoe\Documents\file.txt" }; // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Message.Message.Should().NotContain("JohnDoe"); result.Message.Message.Should().Contain(@"C:\Users\[REDACTED_USER]"); } [TestMethod] public void Process_ShouldScrubEmailInTags() { // Arrange SentryEvent sentryEvent = new(); sentryEvent.SetTag("user", "test@example.com"); sentryEvent.SetTag("path", @"C:\Users\TestUser\AppData\Local\ProtonVPN"); // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Tags["user"].Should().NotContain("test@example.com"); result.Tags["user"].Should().Contain("[REDACTED_EMAIL]"); result.Tags["path"].Should().NotContain("TestUser"); result.Tags["path"].Should().Contain("[REDACTED_USER]"); } [TestMethod] public void Process_ShouldScrubStringInExtras() { // Arrange SentryEvent sentryEvent = new(); sentryEvent.SetExtra("logs", "User admin@proton.me logged in from C:\\Users\\Admin\\Desktop"); // Act SentryEvent result = _processor.Process(sentryEvent); // Assert string logs = result.Extra["logs"] as string; logs.Should().NotContain("admin@proton.me"); logs.Should().NotContain("Admin"); logs.Should().Contain("[REDACTED_EMAIL]"); logs.Should().Contain("[REDACTED_USER]"); } [TestMethod] public void Process_ShouldScrubNestedDictionaryInExtras() { // Arrange SentryEvent sentryEvent = new(); var nestedData = new Dictionary { { "email", "user@example.com" }, { "path", @"C:\Users\TestUser\config.json" }, { "count", 42 } }; sentryEvent.SetExtra("userInfo", nestedData); // Act SentryEvent result = _processor.Process(sentryEvent); // Assert var userInfo = result.Extra["userInfo"] as Dictionary; userInfo.Should().NotBeNull(); userInfo["email"].Should().Be("[REDACTED_EMAIL]"); (userInfo["path"] as string).Should().Contain("[REDACTED_USER]"); userInfo["count"].Should().Be(42); } [TestMethod] public void Process_ShouldHandleNullMessage() { // Arrange SentryEvent sentryEvent = new() { Message = null }; // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Should().NotBeNull(); result.Message.Should().BeNull(); } [TestMethod] public void Process_ShouldHandleEmptyTags() { // Arrange SentryEvent sentryEvent = new(); // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Should().NotBeNull(); } [TestMethod] public void Process_ShouldReturnEventEvenIfScrubbingFails() { // Arrange SentryEvent sentryEvent = new() { Message = "Test message" }; // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Should().NotBeNull(); } [TestMethod] public void Process_ShouldScrubMultiplePatternsInSingleMessage() { // Arrange SentryEvent sentryEvent = new() { Message = @"User john@example.com has files in C:\Users\John\AppData\Local" }; // Act SentryEvent result = _processor.Process(sentryEvent); // Assert result.Message.Message.Should().NotContain("john@example.com"); result.Message.Message.Should().NotContain(@"C:\Users\John"); result.Message.Message.Should().Contain("[REDACTED_EMAIL]"); result.Message.Message.Should().Contain("[REDACTED_USER]"); } }