diff --git a/psalm.xml b/psalm.xml index 55955de..25949d7 100644 --- a/psalm.xml +++ b/psalm.xml @@ -115,13 +115,6 @@ - - - - - - - diff --git a/src/MaskConstants.php b/src/MaskConstants.php index 86c21d9..b752073 100644 --- a/src/MaskConstants.php +++ b/src/MaskConstants.php @@ -28,6 +28,7 @@ final class MaskConstants public const MASK_REDACTED = '***REDACTED***'; public const MASK_FILTERED = '***FILTERED***'; public const MASK_BRACKETS = '[MASKED]'; + public const MASK_REDACTED_BRACKETS = '[REDACTED]'; // Personal identifiers public const MASK_HETU = '***HETU***'; // Finnish SSN diff --git a/src/Streaming/StreamingProcessor.php b/src/Streaming/StreamingProcessor.php index 79ff697..6b1ab42 100644 --- a/src/Streaming/StreamingProcessor.php +++ b/src/Streaming/StreamingProcessor.php @@ -176,10 +176,10 @@ final class StreamingProcessor { $stats = ['processed' => 0, 'masked' => 0, 'errors' => 0]; - foreach ($this->processStream($records) as $record) { + foreach ($records as $record) { $stats['processed']++; - // Count if any masking occurred (simple heuristic) - if (str_contains($record['message'], '***') || str_contains($record['message'], '[')) { + $processed = $this->orchestrator->process($record['message'], $record['context']); + if ($processed !== $record) { $stats['masked']++; } } diff --git a/tests/AdvancedRegexMaskProcessorTest.php b/tests/AdvancedRegexMaskProcessorTest.php index 0a64980..a3b829a 100644 --- a/tests/AdvancedRegexMaskProcessorTest.php +++ b/tests/AdvancedRegexMaskProcessorTest.php @@ -35,7 +35,7 @@ class AdvancedRegexMaskProcessorTest extends TestCase ]; $fieldPaths = [ - "user.ssn" => "[GDPR]", + TestConstants::FIELD_USER_SSN => "[GDPR]", "payment.card" => "[CC]", "contact.email" => FieldMaskConfig::useProcessorPatterns(), // use regex-masked "metadata.session" => "[SESSION]", @@ -48,7 +48,7 @@ class AdvancedRegexMaskProcessorTest extends TestCase { $record = $this->logEntry()->with(message: "Card: 1234567812345678"); $result = ($this->processor)($record)->toArray(); - $this->assertSame("Card: " . MaskConstants::MASK_CC, $result["message"]); + $this->assertSame("Card: " . MaskConstants::MASK_CC, $result[TestConstants::FIELD_MESSAGE]); } public function testMaskEmailInMessage(): void @@ -56,7 +56,7 @@ class AdvancedRegexMaskProcessorTest extends TestCase $record = $this->logEntry()->with(message: "Email: user@example.com"); $result = ($this->processor)($record)->toArray(); - $this->assertSame("Email: " . MaskConstants::MASK_EMAIL, $result["message"]); + $this->assertSame("Email: " . MaskConstants::MASK_EMAIL, $result[TestConstants::FIELD_MESSAGE]); } public function testContextFieldPathReplacements(): void diff --git a/tests/Anonymization/KAnonymizerTest.php b/tests/Anonymization/KAnonymizerTest.php index 30b10d0..0e47013 100644 --- a/tests/Anonymization/KAnonymizerTest.php +++ b/tests/Anonymization/KAnonymizerTest.php @@ -19,11 +19,11 @@ final class KAnonymizerTest extends TestCase $anonymizer = new KAnonymizer(); $anonymizer->registerAgeStrategy('age'); - $record = ['name' => 'John', 'age' => 25]; + $record = ['name' => TestConstants::NAME_FIRST, 'age' => 25]; $result = $anonymizer->anonymize($record); $this->assertSame(TestConstants::AGE_RANGE_20_29, $result['age']); - $this->assertSame('John', $result['name']); + $this->assertSame(TestConstants::NAME_FIRST, $result['name']); } public function testAnonymizeWithAgeStrategyDifferentRanges(): void @@ -84,7 +84,7 @@ final class KAnonymizerTest extends TestCase $anonymizer = new KAnonymizer(); $anonymizer->registerLocationStrategy('zip_code', 3); - $record = ['zip_code' => '12345']; + $record = ['zip_code' => TestConstants::DATA_NUMBER_STRING]; $result = $anonymizer->anonymize($record); $this->assertSame('123**', $result['zip_code']); @@ -115,17 +115,17 @@ final class KAnonymizerTest extends TestCase public function testAnonymizeWithCustomStrategy(): void { $anonymizer = new KAnonymizer(); - $anonymizer->registerCustomStrategy('email', fn(mixed $v): string => explode('@', (string) $v)[1] ?? 'unknown'); + $anonymizer->registerCustomStrategy(TestConstants::CONTEXT_EMAIL, fn(mixed $v): string => explode('@', (string) $v)[1] ?? 'unknown'); - $record = ['email' => 'john@example.com']; + $record = [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_JOHN]; $result = $anonymizer->anonymize($record); - $this->assertSame('example.com', $result['email']); + $this->assertSame(TestConstants::DOMAIN, $result[TestConstants::CONTEXT_EMAIL]); } public function testRegisterStrategy(): void { - $strategy = new GeneralizationStrategy(fn(mixed $v): string => 'masked', 'test'); + $strategy = new GeneralizationStrategy(fn(mixed $v): string => TestConstants::DATA_MASKED, 'test'); $anonymizer = new KAnonymizer(); $anonymizer->registerStrategy('field', $strategy); @@ -133,7 +133,7 @@ final class KAnonymizerTest extends TestCase $record = ['field' => 'value']; $result = $anonymizer->anonymize($record); - $this->assertSame('masked', $result['field']); + $this->assertSame(TestConstants::DATA_MASKED, $result['field']); } public function testAnonymizeIgnoresMissingFields(): void @@ -141,10 +141,10 @@ final class KAnonymizerTest extends TestCase $anonymizer = new KAnonymizer(); $anonymizer->registerAgeStrategy('age'); - $record = ['name' => 'John']; + $record = ['name' => TestConstants::NAME_FIRST]; $result = $anonymizer->anonymize($record); - $this->assertSame(['name' => 'John'], $result); + $this->assertSame(['name' => TestConstants::NAME_FIRST], $result); } public function testAnonymizeBatch(): void @@ -153,7 +153,7 @@ final class KAnonymizerTest extends TestCase $anonymizer->registerAgeStrategy('age'); $records = [ - ['name' => 'John', 'age' => 25], + ['name' => TestConstants::NAME_FIRST, 'age' => 25], ['name' => 'Jane', 'age' => 32], ]; @@ -258,13 +258,13 @@ final class KAnonymizerTest extends TestCase $anonymizer->registerLocationStrategy('zip', 2); $anonymizer->registerDateStrategy('date', 'year'); - $record = ['age' => 28, 'zip' => '12345', 'date' => '2024-06-15', 'name' => 'John']; + $record = ['age' => 28, 'zip' => TestConstants::DATA_NUMBER_STRING, 'date' => '2024-06-15', 'name' => TestConstants::NAME_FIRST]; $result = $anonymizer->anonymize($record); $this->assertSame(TestConstants::AGE_RANGE_20_29, $result['age']); $this->assertSame('12***', $result['zip']); $this->assertSame('2024', $result['date']); - $this->assertSame('John', $result['name']); + $this->assertSame(TestConstants::NAME_FIRST, $result['name']); } public function testFluentInterface(): void diff --git a/tests/ArrayAccessor/ArrayAccessorFactoryTest.php b/tests/ArrayAccessor/ArrayAccessorFactoryTest.php index 3f3b8e2..89b2c97 100644 --- a/tests/ArrayAccessor/ArrayAccessorFactoryTest.php +++ b/tests/ArrayAccessor/ArrayAccessorFactoryTest.php @@ -8,6 +8,7 @@ use Ivuorinen\MonologGdprFilter\ArrayAccessor\ArrayAccessorFactory; use Ivuorinen\MonologGdprFilter\ArrayAccessor\DotArrayAccessor; use Ivuorinen\MonologGdprFilter\Contracts\ArrayAccessorInterface; use PHPUnit\Framework\TestCase; +use Tests\TestConstants; /** * Tests for ArrayAccessorFactory. @@ -29,11 +30,11 @@ final class ArrayAccessorFactoryTest extends TestCase { $factory = ArrayAccessorFactory::default(); $accessor = $factory->create([ - 'user' => ['email' => 'test@example.com'], + 'user' => [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST], ]); - $this->assertTrue($accessor->has('user.email')); - $this->assertSame('test@example.com', $accessor->get('user.email')); + $this->assertTrue($accessor->has(TestConstants::FIELD_USER_EMAIL)); + $this->assertSame(TestConstants::EMAIL_TEST, $accessor->get(TestConstants::FIELD_USER_EMAIL)); } public function testWithClassFactoryMethod(): void diff --git a/tests/ArrayAccessor/ArrayAccessorInterfaceTest.php b/tests/ArrayAccessor/ArrayAccessorInterfaceTest.php index 3c49f20..9c3662d 100644 --- a/tests/ArrayAccessor/ArrayAccessorInterfaceTest.php +++ b/tests/ArrayAccessor/ArrayAccessorInterfaceTest.php @@ -28,22 +28,22 @@ final class ArrayAccessorInterfaceTest extends TestCase { $accessor = new DotArrayAccessor([ 'user' => [ - 'email' => TestConstants::EMAIL_TEST, + TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, ], ]); - $this->assertTrue($accessor->has('user.email')); + $this->assertTrue($accessor->has(TestConstants::FIELD_USER_EMAIL)); } public function testHasReturnsFalseForMissingPath(): void { $accessor = new DotArrayAccessor([ 'user' => [ - 'email' => TestConstants::EMAIL_TEST, + TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, ], ]); - $this->assertFalse($accessor->has('user.name')); + $this->assertFalse($accessor->has(TestConstants::FIELD_USER_NAME)); $this->assertFalse($accessor->has('nonexistent')); } @@ -51,12 +51,12 @@ final class ArrayAccessorInterfaceTest extends TestCase { $accessor = new DotArrayAccessor([ 'user' => [ - 'email' => TestConstants::EMAIL_TEST, + TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, 'age' => 25, ], ]); - $this->assertSame(TestConstants::EMAIL_TEST, $accessor->get('user.email')); + $this->assertSame(TestConstants::EMAIL_TEST, $accessor->get(TestConstants::FIELD_USER_EMAIL)); $this->assertSame(25, $accessor->get('user.age')); } @@ -72,43 +72,43 @@ final class ArrayAccessorInterfaceTest extends TestCase { $accessor = new DotArrayAccessor([]); - $accessor->set('user.email', TestConstants::EMAIL_NEW); + $accessor->set(TestConstants::FIELD_USER_EMAIL, TestConstants::EMAIL_NEW); - $this->assertTrue($accessor->has('user.email')); - $this->assertSame(TestConstants::EMAIL_NEW, $accessor->get('user.email')); + $this->assertTrue($accessor->has(TestConstants::FIELD_USER_EMAIL)); + $this->assertSame(TestConstants::EMAIL_NEW, $accessor->get(TestConstants::FIELD_USER_EMAIL)); } public function testSetOverwritesExistingPath(): void { $accessor = new DotArrayAccessor([ - 'user' => ['email' => 'old@example.com'], + 'user' => [TestConstants::CONTEXT_EMAIL => 'old@example.com'], ]); - $accessor->set('user.email', TestConstants::EMAIL_NEW); + $accessor->set(TestConstants::FIELD_USER_EMAIL, TestConstants::EMAIL_NEW); - $this->assertSame(TestConstants::EMAIL_NEW, $accessor->get('user.email')); + $this->assertSame(TestConstants::EMAIL_NEW, $accessor->get(TestConstants::FIELD_USER_EMAIL)); } public function testDeleteRemovesPath(): void { $accessor = new DotArrayAccessor([ 'user' => [ - 'email' => TestConstants::EMAIL_TEST, + TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, 'name' => 'Test User', ], ]); - $accessor->delete('user.email'); + $accessor->delete(TestConstants::FIELD_USER_EMAIL); - $this->assertFalse($accessor->has('user.email')); - $this->assertTrue($accessor->has('user.name')); + $this->assertFalse($accessor->has(TestConstants::FIELD_USER_EMAIL)); + $this->assertTrue($accessor->has(TestConstants::FIELD_USER_NAME)); } public function testAllReturnsCompleteArray(): void { $data = [ 'user' => [ - 'email' => TestConstants::EMAIL_TEST, + TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, 'profile' => [ 'bio' => 'Hello world', ], diff --git a/tests/Audit/ErrorContextTest.php b/tests/Audit/ErrorContextTest.php index f0cabb2..dd506b3 100644 --- a/tests/Audit/ErrorContextTest.php +++ b/tests/Audit/ErrorContextTest.php @@ -111,10 +111,10 @@ final class ErrorContextTest extends TestCase public function testSanitizesConnectionStrings(): void { - $message = 'Failed: redis://admin:password@localhost:6379'; + $message = 'Failed: redis://admin:' . TestConstants::CONTEXT_PASSWORD . '@localhost:6379'; $context = ErrorContext::create('ConnError', $message); - $this->assertStringNotContainsString('password', $context->message); + $this->assertStringNotContainsString(TestConstants::CONTEXT_PASSWORD, $context->message); $this->assertStringContainsString(TestConstants::MASK_REDACTED_BRACKETS, $context->message); } @@ -141,7 +141,7 @@ final class ErrorContextTest extends TestCase { $context = new ErrorContext( errorType: 'TestError', - message: 'Test message', + message: TestConstants::MESSAGE_DEFAULT, code: 100, file: '/test/file.php', line: 50, @@ -151,14 +151,14 @@ final class ErrorContextTest extends TestCase $array = $context->toArray(); $this->assertArrayHasKey('error_type', $array); - $this->assertArrayHasKey('message', $array); + $this->assertArrayHasKey(TestConstants::FIELD_MESSAGE, $array); $this->assertArrayHasKey('code', $array); $this->assertArrayHasKey('file', $array); $this->assertArrayHasKey('line', $array); $this->assertArrayHasKey('metadata', $array); $this->assertSame('TestError', $array['error_type']); - $this->assertSame('Test message', $array['message']); + $this->assertSame(TestConstants::MESSAGE_DEFAULT, $array[TestConstants::FIELD_MESSAGE]); $this->assertSame(100, $array['code']); } diff --git a/tests/Audit/StructuredAuditLoggerTest.php b/tests/Audit/StructuredAuditLoggerTest.php index b6c8d9a..2ac33e5 100644 --- a/tests/Audit/StructuredAuditLoggerTest.php +++ b/tests/Audit/StructuredAuditLoggerTest.php @@ -43,7 +43,7 @@ final class StructuredAuditLoggerTest extends TestCase $this->logs[] = [ 'path' => $path, 'original' => $original, - 'masked' => $masked + TestConstants::DATA_MASKED => $masked ]; }; } @@ -52,12 +52,12 @@ final class StructuredAuditLoggerTest extends TestCase { $logger = new StructuredAuditLogger($this->createBaseLogger()); - $logger->log('user.email', TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS); + $logger->log(TestConstants::FIELD_USER_EMAIL, TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS); $this->assertCount(1, $this->logs); - $this->assertSame('user.email', $this->logs[0]['path']); + $this->assertSame(TestConstants::FIELD_USER_EMAIL, $this->logs[0]['path']); $this->assertSame(TestConstants::EMAIL_JOHN, $this->logs[0]['original']); - $this->assertSame(TestConstants::MASK_MASKED_BRACKETS, $this->logs[0]['masked']); + $this->assertSame(TestConstants::MASK_MASKED_BRACKETS, $this->logs[0][TestConstants::DATA_MASKED]); } public function testLogWithContext(): void @@ -65,7 +65,7 @@ final class StructuredAuditLoggerTest extends TestCase $logger = new StructuredAuditLogger($this->createBaseLogger()); $context = AuditContext::success(AuditContext::OP_REGEX, 5.0); - $logger->log('user.email', TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS, $context); + $logger->log(TestConstants::FIELD_USER_EMAIL, TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS, $context); $this->assertCount(1, $this->logs); } @@ -75,15 +75,15 @@ final class StructuredAuditLoggerTest extends TestCase $logger = new StructuredAuditLogger($this->createBaseLogger()); $logger->logSuccess( - 'user.ssn', - '123-45-6789', - '[SSN]', + TestConstants::FIELD_USER_SSN, + TestConstants::SSN_US, + TestConstants::MASK_SSN_BRACKETS, AuditContext::OP_REGEX, 10.5 ); $this->assertCount(1, $this->logs); - $this->assertSame('user.ssn', $this->logs[0]['path']); + $this->assertSame(TestConstants::FIELD_USER_SSN, $this->logs[0]['path']); } public function testLogFailure(): void @@ -92,14 +92,14 @@ final class StructuredAuditLoggerTest extends TestCase $error = ErrorContext::create('RegexError', 'Pattern failed'); $logger->logFailure( - 'user.data', + TestConstants::FIELD_USER_DATA, 'sensitive value', AuditContext::OP_REGEX, $error ); $this->assertCount(1, $this->logs); - $this->assertSame('[MASKING_FAILED]', $this->logs[0]['masked']); + $this->assertSame('[MASKING_FAILED]', $this->logs[0][TestConstants::DATA_MASKED]); } public function testLogRecovery(): void @@ -107,7 +107,7 @@ final class StructuredAuditLoggerTest extends TestCase $logger = new StructuredAuditLogger($this->createBaseLogger()); $logger->logRecovery( - 'user.email', + TestConstants::FIELD_USER_EMAIL, TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS, AuditContext::OP_REGEX, @@ -131,14 +131,14 @@ final class StructuredAuditLoggerTest extends TestCase $this->assertCount(1, $this->logs); $this->assertSame(TestConstants::NAME_FULL, $this->logs[0]['original']); - $this->assertSame(TestConstants::NAME_FULL, $this->logs[0]['masked']); + $this->assertSame(TestConstants::NAME_FULL, $this->logs[0][TestConstants::DATA_MASKED]); } public function testWrapStaticFactory(): void { $logger = StructuredAuditLogger::wrap($this->createBaseLogger()); - $logger->log('test.path', 'original', 'masked'); + $logger->log('test.path', 'original', TestConstants::DATA_MASKED); $this->assertCount(1, $this->logs); } @@ -152,7 +152,7 @@ final class StructuredAuditLoggerTest extends TestCase ); $logger = new StructuredAuditLogger($rateLimited); - $logger->log('user.email', TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS); + $logger->log(TestConstants::FIELD_USER_EMAIL, TestConstants::EMAIL_JOHN, TestConstants::MASK_MASKED_BRACKETS); $this->assertCount(1, $this->logs); } @@ -177,7 +177,7 @@ final class StructuredAuditLoggerTest extends TestCase $wrapped = $logger->getWrappedLogger(); // Verify the wrapped logger works by calling it - $wrapped('test.path', 'original', 'masked'); + $wrapped('test.path', 'original', TestConstants::DATA_MASKED); $this->assertCount(1, $this->logs); } @@ -188,7 +188,7 @@ final class StructuredAuditLoggerTest extends TestCase includeTimestamp: false ); - $logger->log('test', 'original', 'masked'); + $logger->log('test', 'original', TestConstants::DATA_MASKED); $this->assertCount(1, $this->logs); } @@ -200,7 +200,7 @@ final class StructuredAuditLoggerTest extends TestCase includeDuration: false ); - $logger->log('test', 'original', 'masked'); + $logger->log('test', 'original', TestConstants::DATA_MASKED); $this->assertCount(1, $this->logs); } diff --git a/tests/Builder/GdprProcessorBuilderEdgeCasesTest.php b/tests/Builder/GdprProcessorBuilderEdgeCasesTest.php index 023a293..16e1367 100644 --- a/tests/Builder/GdprProcessorBuilderEdgeCasesTest.php +++ b/tests/Builder/GdprProcessorBuilderEdgeCasesTest.php @@ -292,7 +292,7 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase #[\Override] public function getFieldPaths(): array { - return ['secret.key' => FieldMaskConfig::replace('[REDACTED]')]; + return ['secret.key' => FieldMaskConfig::replace(TestConstants::MASK_REDACTED_BRACKETS)]; } }; @@ -303,7 +303,7 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase $record = $this->createLogRecord('Test', ['secret' => ['key' => 'sensitive-value']]); $processed = $processor($record); - $this->assertSame('[REDACTED]', $processed->context['secret']['key']); + $this->assertSame(TestConstants::MASK_REDACTED_BRACKETS, $processed->context['secret']['key']); } #[Test] @@ -313,16 +313,16 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase $processor = GdprProcessorBuilder::create() ->withArrayAccessorFactory($factory) - ->addFieldPath('user.email', MaskConstants::MASK_EMAIL) + ->addFieldPath(TestConstants::FIELD_USER_EMAIL, MaskConstants::MASK_EMAIL) ->build(); $record = $this->createLogRecord('Test', [ - 'user' => ['email' => 'test@example.com'], + 'user' => [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST], ]); $processed = $processor($record); - $this->assertSame(MaskConstants::MASK_EMAIL, $processed->context['user']['email']); + $this->assertSame(MaskConstants::MASK_EMAIL, $processed->context['user'][TestConstants::CONTEXT_EMAIL]); } #[Test] @@ -330,13 +330,13 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase { $processor = GdprProcessorBuilder::create() ->withMaxDepth(2) - ->addPattern('/secret/', TestConstants::MASK_MASKED_BRACKETS) + ->addPattern(TestConstants::PATTERN_SECRET, TestConstants::MASK_MASKED_BRACKETS) ->build(); $record = $this->createLogRecord('Test', [ 'level1' => [ 'level2' => [ - 'level3' => 'secret data', + 'level3' => TestConstants::MESSAGE_SECRET_DATA, ], ], ]); @@ -353,13 +353,13 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase $auditLogs = []; $processor = GdprProcessorBuilder::create() - ->addFieldPath('password', MaskConstants::MASK_REDACTED) + ->addFieldPath(TestConstants::CONTEXT_PASSWORD, MaskConstants::MASK_REDACTED) ->withAuditLogger(function ($path, $original, $masked) use (&$auditLogs): void { - $auditLogs[] = ['path' => $path, 'original' => $original, 'masked' => $masked]; + $auditLogs[] = ['path' => $path, 'original' => $original, TestConstants::DATA_MASKED => $masked]; }) ->build(); - $record = $this->createLogRecord('Test', ['password' => 'secret123']); + $record = $this->createLogRecord('Test', [TestConstants::CONTEXT_PASSWORD => 'secret123']); $processor($record); $this->assertNotEmpty($auditLogs); @@ -390,21 +390,21 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase { $processor = GdprProcessorBuilder::create() ->addFieldPaths([ - 'user.email' => MaskConstants::MASK_EMAIL, + TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL, 'user.phone' => MaskConstants::MASK_PHONE, ]) ->build(); $record = $this->createLogRecord('Test', [ 'user' => [ - 'email' => 'test@example.com', + TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, 'phone' => '555-1234', ], ]); $processed = $processor($record); - $this->assertSame(MaskConstants::MASK_EMAIL, $processed->context['user']['email']); + $this->assertSame(MaskConstants::MASK_EMAIL, $processed->context['user'][TestConstants::CONTEXT_EMAIL]); $this->assertSame(MaskConstants::MASK_PHONE, $processed->context['user']['phone']); } @@ -413,15 +413,15 @@ final class GdprProcessorBuilderEdgeCasesTest extends TestCase { $processor = GdprProcessorBuilder::create() ->addPatterns([ - '/\d{3}-\d{2}-\d{4}/' => '[SSN]', - '/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/' => '[EMAIL]', + TestConstants::PATTERN_SSN_FORMAT => TestConstants::MASK_SSN_BRACKETS, + TestConstants::PATTERN_EMAIL_FULL => TestConstants::MASK_EMAIL_BRACKETS, ]) ->build(); - $record = $this->createLogRecord('SSN: 123-45-6789, Email: user@example.com'); + $record = $this->createLogRecord('SSN: ' . TestConstants::SSN_US . ', Email: ' . TestConstants::EMAIL_USER); $processed = $processor($record); - $this->assertStringContainsString('[SSN]', $processed->message); - $this->assertStringContainsString('[EMAIL]', $processed->message); + $this->assertStringContainsString(TestConstants::MASK_SSN_BRACKETS, $processed->message); + $this->assertStringContainsString(TestConstants::MASK_EMAIL_BRACKETS, $processed->message); } } diff --git a/tests/Builder/GdprProcessorBuilderTest.php b/tests/Builder/GdprProcessorBuilderTest.php index 84c3fbf..f018c95 100644 --- a/tests/Builder/GdprProcessorBuilderTest.php +++ b/tests/Builder/GdprProcessorBuilderTest.php @@ -58,7 +58,7 @@ final class GdprProcessorBuilderTest extends TestCase { $patterns = [ TestConstants::PATTERN_DIGITS => TestConstants::MASK_DIGITS_BRACKETS, - TestConstants::PATTERN_TEST => '[TEST]', + TestConstants::PATTERN_TEST => TestConstants::REPLACEMENT_TEST, ]; $builder = GdprProcessorBuilder::create()->addPatterns($patterns); @@ -70,7 +70,7 @@ final class GdprProcessorBuilderTest extends TestCase { $builder = GdprProcessorBuilder::create() ->addPattern(TestConstants::PATTERN_DIGITS, TestConstants::MASK_DIGITS_BRACKETS) - ->setPatterns([TestConstants::PATTERN_TEST => '[TEST]']); + ->setPatterns([TestConstants::PATTERN_TEST => TestConstants::REPLACEMENT_TEST]); $patterns = $builder->getPatterns(); @@ -82,7 +82,7 @@ final class GdprProcessorBuilderTest extends TestCase public function testAddFieldPath(): void { $builder = GdprProcessorBuilder::create() - ->addFieldPath(TestConstants::CONTEXT_EMAIL, FieldMaskConfig::replace('[EMAIL]')); + ->addFieldPath(TestConstants::CONTEXT_EMAIL, FieldMaskConfig::replace(TestConstants::MASK_EMAIL_BRACKETS)); $this->assertArrayHasKey(TestConstants::CONTEXT_EMAIL, $builder->getFieldPaths()); } @@ -90,7 +90,7 @@ final class GdprProcessorBuilderTest extends TestCase public function testAddFieldPaths(): void { $fieldPaths = [ - TestConstants::CONTEXT_EMAIL => FieldMaskConfig::replace('[EMAIL]'), + TestConstants::CONTEXT_EMAIL => FieldMaskConfig::replace(TestConstants::MASK_EMAIL_BRACKETS), TestConstants::CONTEXT_PASSWORD => FieldMaskConfig::remove(), ]; @@ -128,7 +128,7 @@ final class GdprProcessorBuilderTest extends TestCase }; $processor = GdprProcessorBuilder::create() - ->addFieldPath('field', FieldMaskConfig::replace('[MASKED]')) + ->addFieldPath('field', FieldMaskConfig::replace(MaskConstants::MASK_BRACKETS)) ->withAuditLogger($auditLogger) ->build(); @@ -229,7 +229,7 @@ final class GdprProcessorBuilderTest extends TestCase public function getPatterns(): array { - return ['/secret/' => '[SECRET]']; + return [TestConstants::PATTERN_SECRET => TestConstants::MASK_SECRET_BRACKETS]; } }; @@ -297,7 +297,7 @@ final class GdprProcessorBuilderTest extends TestCase public function getPatterns(): array { - return ['/secret/' => '[SECRET]']; + return [TestConstants::PATTERN_SECRET => TestConstants::MASK_SECRET_BRACKETS]; } }; diff --git a/tests/Builder/PluginAwareProcessorTest.php b/tests/Builder/PluginAwareProcessorTest.php index 42e383e..ae0051c 100644 --- a/tests/Builder/PluginAwareProcessorTest.php +++ b/tests/Builder/PluginAwareProcessorTest.php @@ -33,7 +33,7 @@ final class PluginAwareProcessorTest extends TestCase }; $processor = GdprProcessorBuilder::create() - ->addPattern('/TEST/', '[MASKED]') + ->addPattern('/TEST/', MaskConstants::MASK_BRACKETS) ->addPlugin($plugin) ->buildWithPlugins(); @@ -48,7 +48,7 @@ final class PluginAwareProcessorTest extends TestCase $result = $processor($record); // Message should be uppercased, then 'TEST' should be masked - $this->assertStringContainsString('[MASKED]', $result->message); + $this->assertStringContainsString(TestConstants::MASK_MASKED_BRACKETS, $result->message); } public function testInvokeAppliesPostProcessing(): void @@ -263,7 +263,7 @@ final class PluginAwareProcessorTest extends TestCase ->buildWithPlugins(); $this->assertInstanceOf(PluginAwareProcessor::class, $processor); - $this->assertSame(MaskConstants::MASK_GENERIC . ' message', $processor->regExpMessage('test message')); + $this->assertSame(MaskConstants::MASK_GENERIC . ' message', $processor->regExpMessage(TestConstants::MESSAGE_TEST_LOWERCASE)); } public function testRecursiveMaskDelegates(): void @@ -282,9 +282,9 @@ final class PluginAwareProcessorTest extends TestCase $this->assertInstanceOf(PluginAwareProcessor::class, $processor); - $result = $processor->recursiveMask(['key' => 'test value']); + $result = $processor->recursiveMask(['key' => TestConstants::VALUE_TEST]); - $this->assertSame(MaskConstants::MASK_GENERIC . ' value', $result['key']); + $this->assertSame(MaskConstants::MASK_GENERIC . TestConstants::VALUE_SUFFIX, $result['key']); } public function testSetAuditLoggerDelegates(): void diff --git a/tests/ConditionalRuleFactoryInstanceTest.php b/tests/ConditionalRuleFactoryInstanceTest.php index e3915f7..daaf919 100644 --- a/tests/ConditionalRuleFactoryInstanceTest.php +++ b/tests/ConditionalRuleFactoryInstanceTest.php @@ -48,18 +48,18 @@ final class ConditionalRuleFactoryInstanceTest extends TestCase public function testContextFieldRuleWithPresentField(): void { $factory = new ConditionalRuleFactory(); - $rule = $factory->contextFieldRule('user_id'); + $rule = $factory->contextFieldRule(TestConstants::CONTEXT_USER_ID); - $record = $this->createLogRecord('Test message', ['user_id' => 123]); + $record = $this->createLogRecord(TestConstants::MESSAGE_DEFAULT, [TestConstants::CONTEXT_USER_ID => 123]); $this->assertTrue($rule($record)); } public function testContextFieldRuleWithMissingField(): void { $factory = new ConditionalRuleFactory(); - $rule = $factory->contextFieldRule('user_id'); + $rule = $factory->contextFieldRule(TestConstants::CONTEXT_USER_ID); - $record = $this->createLogRecord('Test message', []); + $record = $this->createLogRecord(TestConstants::MESSAGE_DEFAULT, []); $this->assertFalse($rule($record)); } @@ -185,14 +185,14 @@ final class ConditionalRuleFactoryInstanceTest extends TestCase $instanceFactory = new ConditionalRuleFactory(); // Create rules using both methods - $instanceFieldRule = $instanceFactory->contextFieldRule('user.email'); - $staticFieldRule = ConditionalRuleFactory::createContextFieldRule('user.email'); + $instanceFieldRule = $instanceFactory->contextFieldRule(TestConstants::FIELD_USER_EMAIL); + $staticFieldRule = ConditionalRuleFactory::createContextFieldRule(TestConstants::FIELD_USER_EMAIL); $instanceValueRule = $instanceFactory->contextValueRule('type', 'admin'); $staticValueRule = ConditionalRuleFactory::createContextValueRule('type', 'admin'); $record = $this->createLogRecord('Test', [ - 'user' => ['email' => 'test@example.com'], + 'user' => [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST], 'type' => 'admin', ]); diff --git a/tests/ContextProcessorTest.php b/tests/ContextProcessorTest.php index ba2e1f9..969fa11 100644 --- a/tests/ContextProcessorTest.php +++ b/tests/ContextProcessorTest.php @@ -63,7 +63,7 @@ final class ContextProcessorTest extends TestCase { $regexProcessor = fn(string $val): string => $val; $processor = new ContextProcessor( - [TestConstants::CONTEXT_PASSWORD => FieldMaskConfig::replace('[REDACTED]')], + [TestConstants::CONTEXT_PASSWORD => FieldMaskConfig::replace(TestConstants::MASK_REDACTED_BRACKETS)], [], null, $regexProcessor @@ -73,7 +73,7 @@ final class ContextProcessorTest extends TestCase $processed = $processor->maskFieldPaths($accessor); $this->assertSame([TestConstants::CONTEXT_PASSWORD], $processed); - $this->assertSame('[REDACTED]', $accessor->get(TestConstants::CONTEXT_PASSWORD)); + $this->assertSame(TestConstants::MASK_REDACTED_BRACKETS, $accessor->get(TestConstants::CONTEXT_PASSWORD)); } public function testMaskFieldPathsSkipsNonExistentPaths(): void diff --git a/tests/Exceptions/AuditLoggingExceptionComprehensiveTest.php b/tests/Exceptions/AuditLoggingExceptionComprehensiveTest.php index 2a9e4a9..f228bb7 100644 --- a/tests/Exceptions/AuditLoggingExceptionComprehensiveTest.php +++ b/tests/Exceptions/AuditLoggingExceptionComprehensiveTest.php @@ -98,14 +98,14 @@ final class AuditLoggingExceptionComprehensiveTest extends TestCase $value = ['data' => 'test']; $exception = AuditLoggingException::serializationFailed( - 'user.data', + TestConstants::FIELD_USER_DATA, $value, 'JSON encoding failed' ); $this->assertInstanceOf(AuditLoggingException::class, $exception); $message = $exception->getMessage(); - $this->assertStringContainsString('user.data', $message); + $this->assertStringContainsString(TestConstants::FIELD_USER_DATA, $message); $this->assertStringContainsString('JSON encoding failed', $message); $this->assertStringContainsString('serialization_failure', $message); } diff --git a/tests/Exceptions/CustomExceptionsTest.php b/tests/Exceptions/CustomExceptionsTest.php index bcbec42..e951f64 100644 --- a/tests/Exceptions/CustomExceptionsTest.php +++ b/tests/Exceptions/CustomExceptionsTest.php @@ -228,13 +228,13 @@ class CustomExceptionsTest extends TestCase public function testAuditLoggingExceptionSerializationFailed(): void { $exception = AuditLoggingException::serializationFailed( - 'user.data', + TestConstants::FIELD_USER_DATA, ['circular' => 'reference'], 'Circular reference detected' ); $this->assertStringContainsString( - "Audit data serialization failed for path 'user.data'", + "Audit data serialization failed for path '" . TestConstants::FIELD_USER_DATA . "'", $exception->getMessage() ); $this->assertStringContainsString('Circular reference detected', $exception->getMessage()); diff --git a/tests/Exceptions/MaskingOperationFailedExceptionTest.php b/tests/Exceptions/MaskingOperationFailedExceptionTest.php index 3ab5205..7b051b3 100644 --- a/tests/Exceptions/MaskingOperationFailedExceptionTest.php +++ b/tests/Exceptions/MaskingOperationFailedExceptionTest.php @@ -7,6 +7,7 @@ namespace Tests\Exceptions; use Ivuorinen\MonologGdprFilter\Exceptions\MaskingOperationFailedException; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Tests\TestConstants; #[CoversClass(MaskingOperationFailedException::class)] final class MaskingOperationFailedExceptionTest extends TestCase @@ -77,7 +78,7 @@ final class MaskingOperationFailedExceptionTest extends TestCase $previous = new \RuntimeException('Inner error'); $exception = MaskingOperationFailedException::fieldPathMaskingFailed( - 'user.data', + TestConstants::FIELD_USER_DATA, ['complex' => 'value'], 'Failed', $previous diff --git a/tests/Factory/AuditLoggerFactoryTest.php b/tests/Factory/AuditLoggerFactoryTest.php index 0c36358..96137af 100644 --- a/tests/Factory/AuditLoggerFactoryTest.php +++ b/tests/Factory/AuditLoggerFactoryTest.php @@ -9,6 +9,7 @@ use Ivuorinen\MonologGdprFilter\Factory\AuditLoggerFactory; use Ivuorinen\MonologGdprFilter\RateLimitedAuditLogger; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Tests\TestConstants; #[CoversClass(AuditLoggerFactory::class)] final class AuditLoggerFactoryTest extends TestCase @@ -66,12 +67,12 @@ final class AuditLoggerFactoryTest extends TestCase $storage = []; $logger = $factory->createArrayLogger($storage); - $logger('test.path', 'original', 'masked'); + $logger('test.path', 'original', TestConstants::DATA_MASKED); $this->assertCount(1, $storage); $this->assertSame('test.path', $storage[0]['path']); $this->assertSame('original', $storage[0]['original']); - $this->assertSame('masked', $storage[0]['masked']); + $this->assertSame(TestConstants::DATA_MASKED, $storage[0][TestConstants::DATA_MASKED]); $this->assertArrayHasKey('timestamp', $storage[0]); } @@ -90,7 +91,7 @@ final class AuditLoggerFactoryTest extends TestCase $logger = $factory->createNullLogger(); // Should not throw - $logger('path', 'original', 'masked'); + $logger('path', 'original', TestConstants::DATA_MASKED); $this->assertTrue(true); } @@ -109,11 +110,11 @@ final class AuditLoggerFactoryTest extends TestCase $factory = AuditLoggerFactory::create(); $calls = []; $callback = function (string $path, mixed $original, mixed $masked) use (&$calls): void { - $calls[] = ['path' => $path, 'original' => $original, 'masked' => $masked]; + $calls[] = ['path' => $path, 'original' => $original, TestConstants::DATA_MASKED => $masked]; }; $logger = $factory->createCallbackLogger($callback); - $logger('test.path', 'original', 'masked'); + $logger('test.path', 'original', TestConstants::DATA_MASKED); $this->assertCount(1, $calls); $this->assertSame('test.path', $calls[0]['path']); diff --git a/tests/GdprProcessorComprehensiveTest.php b/tests/GdprProcessorComprehensiveTest.php index 5c33ef7..0601438 100644 --- a/tests/GdprProcessorComprehensiveTest.php +++ b/tests/GdprProcessorComprehensiveTest.php @@ -175,7 +175,7 @@ final class GdprProcessorComprehensiveTest extends TestCase // Should not throw exception GdprProcessor::validatePatternsArray([ TestConstants::PATTERN_DIGITS => Mask::MASK_MASKED, - '/[a-z]+/' => Mask::MASK_REDACTED, + TestConstants::PATTERN_SAFE => Mask::MASK_REDACTED, ]); $this->assertTrue(true); @@ -202,7 +202,7 @@ final class GdprProcessorComprehensiveTest extends TestCase $data = [ 'level1' => [ 'level2' => [ - 'value' => 'secret data', + 'value' => TestConstants::MESSAGE_SECRET_DATA, ], ], ]; diff --git a/tests/GdprProcessorEdgeCasesTest.php b/tests/GdprProcessorEdgeCasesTest.php index 6112a08..69b7c07 100644 --- a/tests/GdprProcessorEdgeCasesTest.php +++ b/tests/GdprProcessorEdgeCasesTest.php @@ -59,10 +59,10 @@ final class GdprProcessorEdgeCasesTest extends TestCase ); // Call maskMessage directly - $result = $processor->maskMessage('test value'); + $result = $processor->maskMessage(TestConstants::VALUE_TEST); // Should work normally - $this->assertSame(Mask::MASK_MASKED . ' value', $result); + $this->assertSame(Mask::MASK_MASKED . TestConstants::VALUE_SUFFIX, $result); // Now test with patterns that might cause issues // Note: It's hard to trigger preg_replace null return in normal usage @@ -79,7 +79,7 @@ final class GdprProcessorEdgeCasesTest extends TestCase // Test recursiveMask with array $data = [ 'level1' => [ - 'level2' => 'secret data', + 'level2' => TestConstants::MESSAGE_SECRET_DATA, ], ]; diff --git a/tests/GdprProcessorMethodsTest.php b/tests/GdprProcessorMethodsTest.php index 3a231ad..23b0f70 100644 --- a/tests/GdprProcessorMethodsTest.php +++ b/tests/GdprProcessorMethodsTest.php @@ -33,7 +33,7 @@ class GdprProcessorMethodsTest extends TestCase ]; $fieldPaths = [ TestConstants::FIELD_USER_EMAIL => FieldMaskConfig::useProcessorPatterns(), - 'user.ssn' => FieldMaskConfig::remove(), + TestConstants::FIELD_USER_SSN => FieldMaskConfig::remove(), 'user.card' => FieldMaskConfig::replace('MASKED'), ]; $context = [ @@ -75,7 +75,7 @@ class GdprProcessorMethodsTest extends TestCase { $patterns = []; $fieldPaths = [ - 'user.ssn' => FieldMaskConfig::remove(), + TestConstants::FIELD_USER_SSN => FieldMaskConfig::remove(), ]; $context = ['user' => ['ssn' => self::TEST_HETU]]; diff --git a/tests/GdprProcessorTest.php b/tests/GdprProcessorTest.php index 47e73a7..186885d 100644 --- a/tests/GdprProcessorTest.php +++ b/tests/GdprProcessorTest.php @@ -58,7 +58,7 @@ class GdprProcessorTest extends TestCase { $patterns = DefaultPatterns::get(); $fieldPaths = [ - 'user.ssn' => FieldMaskConfig::remove(), + TestConstants::FIELD_USER_SSN => FieldMaskConfig::remove(), ]; $processor = $this->createProcessor($patterns, $fieldPaths); $record = new LogRecord( @@ -284,7 +284,7 @@ class GdprProcessorTest extends TestCase $validPatterns = [ TestConstants::PATTERN_TEST => 'REPLACED', TestConstants::PATTERN_DIGITS => 'NUMBER', - '/[a-z]+/' => 'LETTERS' + TestConstants::PATTERN_SAFE => 'LETTERS' ]; $processor = $this->createProcessor($validPatterns); diff --git a/tests/InputValidation/FieldMaskConfigValidationTest.php b/tests/InputValidation/FieldMaskConfigValidationTest.php index fa8a200..85a906e 100644 --- a/tests/InputValidation/FieldMaskConfigValidationTest.php +++ b/tests/InputValidation/FieldMaskConfigValidationTest.php @@ -70,9 +70,9 @@ class FieldMaskConfigValidationTest extends TestCase public function regexMaskThrowsExceptionForIncompleteRegexPattern(): void { $this->expectException(InvalidRegexPatternException::class); - $this->expectExceptionMessage("Invalid regex pattern '/unclosed'"); + $this->expectExceptionMessage("Invalid regex pattern '" . TestConstants::PATTERN_INVALID_UNCLOSED . "'"); - FieldMaskConfig::regexMask('/unclosed'); + FieldMaskConfig::regexMask(TestConstants::PATTERN_INVALID_UNCLOSED); } #[Test] @@ -217,7 +217,7 @@ class FieldMaskConfigValidationTest extends TestCase #[Test] public function toArrayAndFromArrayRoundTripWorksCorrectly(): void { - $original = FieldMaskConfig::replace('[REDACTED]'); + $original = FieldMaskConfig::replace(TestConstants::MASK_REDACTED_BRACKETS); $array = $original->toArray(); $restored = FieldMaskConfig::fromArray($array); diff --git a/tests/InputValidation/GdprProcessorValidationTest.php b/tests/InputValidation/GdprProcessorValidationTest.php index 092abe0..e22a147 100644 --- a/tests/InputValidation/GdprProcessorValidationTest.php +++ b/tests/InputValidation/GdprProcessorValidationTest.php @@ -144,7 +144,7 @@ class GdprProcessorValidationTest extends TestCase $processor = new GdprProcessor([], [ TestConstants::FIELD_USER_EMAIL => FieldMaskConfig::remove(), TestConstants::FIELD_USER_NAME => 'masked_value', - 'payment.card' => FieldMaskConfig::replace('[CARD]') + 'payment.card' => FieldMaskConfig::replace(TestConstants::MASK_CARD_BRACKETS) ]); $this->assertInstanceOf(GdprProcessor::class, $processor); @@ -429,7 +429,7 @@ class GdprProcessorValidationTest extends TestCase { $processor = new GdprProcessor([], [ TestConstants::FIELD_USER_EMAIL => FieldMaskConfig::remove(), - TestConstants::FIELD_USER_NAME => FieldMaskConfig::replace('[REDACTED]'), + TestConstants::FIELD_USER_NAME => FieldMaskConfig::replace(TestConstants::MASK_REDACTED_BRACKETS), 'user.phone' => FieldMaskConfig::regexMask('/\d/', '*'), 'metadata.ip' => 'simple_string_replacement' ]); diff --git a/tests/InputValidatorTest.php b/tests/InputValidatorTest.php index abd0802..5efe8d7 100644 --- a/tests/InputValidatorTest.php +++ b/tests/InputValidatorTest.php @@ -84,7 +84,7 @@ final class InputValidatorTest extends TestCase { InputValidator::validatePatterns([ TestConstants::PATTERN_SSN_FORMAT => MaskConstants::MASK_SSN_PATTERN, - '/[a-z]+/' => 'REDACTED', + TestConstants::PATTERN_SAFE => TestConstants::MASK_REDACTED_PLAIN, ]); $this->assertTrue(true); @@ -140,7 +140,7 @@ final class InputValidatorTest extends TestCase InputValidator::validateFieldPaths([ TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL_PATTERN, TestConstants::FIELD_USER_PASSWORD => FieldMaskConfig::remove(), - 'user.ssn' => $ssnConfig, + TestConstants::FIELD_USER_SSN => $ssnConfig, ]); $this->assertTrue(true); @@ -297,7 +297,7 @@ final class InputValidatorTest extends TestCase InputValidator::validateDataTypeMasks([ 'integer' => MaskConstants::MASK_GENERIC, 'double' => MaskConstants::MASK_GENERIC, - 'string' => 'REDACTED', + 'string' => TestConstants::MASK_REDACTED_PLAIN, 'boolean' => MaskConstants::MASK_GENERIC, 'NULL' => 'null', 'array' => '[]', diff --git a/tests/JsonMaskingTest.php b/tests/JsonMaskingTest.php index d52a6d0..8c44a7d 100644 --- a/tests/JsonMaskingTest.php +++ b/tests/JsonMaskingTest.php @@ -28,7 +28,7 @@ class JsonMaskingTest extends TestCase TestConstants::PATTERN_EMAIL_FULL => MaskConstants::MASK_EMAIL ]); - $message = 'User data: {"email": "user@example.com", "name": "John Doe"}'; + $message = 'User data: {"' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_USER . '", "name": "' . TestConstants::NAME_FULL . '"}'; $result = $processor->regExpMessage($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -47,7 +47,7 @@ class JsonMaskingTest extends TestCase TestConstants::PATTERN_EMAIL_FULL => MaskConstants::MASK_EMAIL ]); - $message = 'Users: [{"email": "admin@example.com"}, {"email": "user@test.com"}]'; + $message = 'Users: [{"' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_ADMIN . '"}, {"' . TestConstants::CONTEXT_EMAIL . '": "user@test.com"}]'; $result = $processor->regExpMessage($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -69,7 +69,7 @@ class JsonMaskingTest extends TestCase ]); $message = 'Complex data: {"user": {"contact": ' - . '{"email": "nested@example.com", "ssn": "' . TestConstants::SSN_US . '"}, "id": 42}}'; + . '{"' . TestConstants::CONTEXT_EMAIL . '": "nested@example.com", "ssn": "' . TestConstants::SSN_US . '"}, "id": 42}}'; $result = $processor->regExpMessage($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -91,7 +91,7 @@ class JsonMaskingTest extends TestCase TestConstants::PATTERN_EMAIL_FULL => MaskConstants::MASK_EMAIL ]); - $message = 'Request: {"email": "req@example.com"} Response: {"email": "resp@test.com", "status": "ok"}'; + $message = 'Request: {"' . TestConstants::CONTEXT_EMAIL . '": "req@example.com"} Response: {"' . TestConstants::CONTEXT_EMAIL . '": "resp@test.com", "status": "ok"}'; $result = $processor->regExpMessage($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -135,7 +135,7 @@ class JsonMaskingTest extends TestCase TestConstants::PATTERN_EMAIL_FULL => MaskConstants::MASK_EMAIL ]); - $message = 'Data: {"email": "user@example.com", "message": "Hello \"world\"", "unicode": "café ñoño"}'; + $message = 'Data: {"' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_USER . '", "' . TestConstants::FIELD_MESSAGE . '": "Hello \"world\"", "unicode": "café ñoño"}'; $result = $processor->regExpMessage($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -159,7 +159,7 @@ class JsonMaskingTest extends TestCase ['integer' => MaskConstants::MASK_INT, 'string' => MaskConstants::MASK_STRING] ); - $message = 'Data: {"email": "user@example.com", "id": 12345, "active": true}'; + $message = 'Data: {"' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_USER . '", "id": 12345, "active": true}'; $result = $processor->regExpMessage($message); $extractedJson = $this->extractJsonFromMessage($result); @@ -187,7 +187,7 @@ class JsonMaskingTest extends TestCase $auditLogger ); - $message = 'User: {"email": "test@example.com", "name": "Test User"}'; + $message = 'User: {"' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_TEST . '", "name": "Test User"}'; $result = $processor->regExpMessage($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -218,7 +218,7 @@ class JsonMaskingTest extends TestCase new DateTimeImmutable(), 'test', Level::Info, - 'API Response: {"user": {"email": "api@example.com"}, "status": "success"}', + 'API Response: {"user": {"' . TestConstants::CONTEXT_EMAIL . '": "api@example.com"}, "status": "success"}', [] ); @@ -253,7 +253,7 @@ class JsonMaskingTest extends TestCase new DateTimeImmutable(), 'test', Level::Error, - 'Error data: {"email": "error@example.com"}', + 'Error data: {"' . TestConstants::CONTEXT_EMAIL . '": "error@example.com"}', [] ); @@ -266,7 +266,7 @@ class JsonMaskingTest extends TestCase new DateTimeImmutable(), 'test', Level::Info, - 'Info data: {"email": "info@example.com"}', + 'Info data: {"' . TestConstants::CONTEXT_EMAIL . '": "info@example.com"}', [] ); @@ -286,18 +286,18 @@ class JsonMaskingTest extends TestCase "users": [ { "id": 1, - "email": "john@example.com", + "' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_JOHN . '", "contacts": { "phone": "' . TestConstants::PHONE_US . '", "emergency": { - "email": "emergency@example.com", + "' . TestConstants::CONTEXT_EMAIL . '": "emergency@example.com", "phone": "' . TestConstants::PHONE_US_ALT . '" } } }, { "id": 2, - "email": "jane@test.com", + "' . TestConstants::CONTEXT_EMAIL . '": "jane@test.com", "contacts": { "phone": "+1-555-456-7890" } @@ -310,7 +310,7 @@ class JsonMaskingTest extends TestCase $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); $this->assertStringContainsString(MaskConstants::MASK_PHONE, $result); - $this->assertStringNotContainsString('john@example.com', $result); + $this->assertStringNotContainsString(TestConstants::EMAIL_JOHN, $result); $this->assertStringNotContainsString('jane@test.com', $result); $this->assertStringNotContainsString('emergency@example.com', $result); $this->assertStringNotContainsString(TestConstants::PHONE_US, $result); @@ -420,7 +420,7 @@ class JsonMaskingTest extends TestCase TestConstants::PATTERN_EMAIL_FULL => MaskConstants::MASK_EMAIL ]); - $message = 'Data: {"email": "user@example.com", "optional": null, "empty": ""}'; + $message = 'Data: {"' . TestConstants::CONTEXT_EMAIL . '": "' . TestConstants::EMAIL_USER . '", "optional": null, "empty": ""}'; $result = $processor->regExpMessage($message); $extractedJson = $this->extractJsonFromMessage($result); diff --git a/tests/MaskingOrchestratorTest.php b/tests/MaskingOrchestratorTest.php index f261d45..f4dc851 100644 --- a/tests/MaskingOrchestratorTest.php +++ b/tests/MaskingOrchestratorTest.php @@ -25,7 +25,7 @@ final class MaskingOrchestratorTest extends TestCase $result = $orchestrator->process('This is a test message', []); - $this->assertSame('This is a ' . MaskConstants::MASK_GENERIC . ' message', $result['message']); + $this->assertSame('This is a ' . MaskConstants::MASK_GENERIC . ' message', $result[TestConstants::FIELD_MESSAGE]); $this->assertSame([], $result['context']); } @@ -35,9 +35,9 @@ final class MaskingOrchestratorTest extends TestCase [TestConstants::PATTERN_TEST => MaskConstants::MASK_GENERIC] ); - $result = $orchestrator->process('message', ['key' => TestConstants::VALUE_TEST]); + $result = $orchestrator->process(TestConstants::FIELD_MESSAGE, ['key' => TestConstants::VALUE_TEST]); - $this->assertSame('message', $result['message']); + $this->assertSame(TestConstants::FIELD_MESSAGE, $result[TestConstants::FIELD_MESSAGE]); $this->assertSame(MaskConstants::MASK_GENERIC . TestConstants::VALUE_SUFFIX, $result['context']['key']); } @@ -48,7 +48,7 @@ final class MaskingOrchestratorTest extends TestCase [TestConstants::CONTEXT_EMAIL => FieldMaskConfig::replace(TestConstants::MASK_EMAIL_BRACKETS)] ); - $result = $orchestrator->process('message', [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST]); + $result = $orchestrator->process(TestConstants::FIELD_MESSAGE, [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST]); $this->assertSame(TestConstants::MASK_EMAIL_BRACKETS, $result['context'][TestConstants::CONTEXT_EMAIL]); } @@ -61,7 +61,7 @@ final class MaskingOrchestratorTest extends TestCase ['name' => fn(mixed $val): string => strtoupper((string) $val)] ); - $result = $orchestrator->process('message', ['name' => 'john']); + $result = $orchestrator->process(TestConstants::FIELD_MESSAGE, ['name' => 'john']); $this->assertSame('JOHN', $result['context']['name']); } @@ -80,12 +80,12 @@ final class MaskingOrchestratorTest extends TestCase public function testRegExpMessageMasksPatterns(): void { $orchestrator = new MaskingOrchestrator( - [TestConstants::PATTERN_SSN_FORMAT => '[SSN]'] + [TestConstants::PATTERN_SSN_FORMAT => TestConstants::MASK_SSN_BRACKETS] ); $result = $orchestrator->regExpMessage('SSN: 123-45-6789'); - $this->assertSame('SSN: [SSN]', $result); + $this->assertSame(TestConstants::EXPECTED_SSN_MASKED, $result); } public function testRegExpMessagePreservesEmptyString(): void @@ -115,7 +115,7 @@ final class MaskingOrchestratorTest extends TestCase [TestConstants::PATTERN_TEST => MaskConstants::MASK_GENERIC] ); - $result = $orchestrator->recursiveMask('test string'); + $result = $orchestrator->recursiveMask(TestConstants::MESSAGE_TEST_STRING); $this->assertSame(MaskConstants::MASK_GENERIC . ' string', $result); } @@ -136,7 +136,7 @@ final class MaskingOrchestratorTest extends TestCase public function testCreateWithValidParameters(): void { $orchestrator = MaskingOrchestrator::create( - [TestConstants::PATTERN_DIGITS => '[DIGITS]'], + [TestConstants::PATTERN_DIGITS => TestConstants::MASK_DIGITS_BRACKETS], [], [], null, @@ -178,7 +178,7 @@ final class MaskingOrchestratorTest extends TestCase $orchestrator = new MaskingOrchestrator( [], - ['field' => FieldMaskConfig::replace('[MASKED]')] + ['field' => FieldMaskConfig::replace(MaskConstants::MASK_BRACKETS)] ); $orchestrator->setAuditLogger($auditLogger); @@ -218,11 +218,11 @@ final class MaskingOrchestratorTest extends TestCase [ TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, 'name' => 'john', - 'message' => 'test' + TestConstants::FIELD_MESSAGE => 'test' ] ); - $this->assertSame('Hello ' . MaskConstants::MASK_GENERIC, $result['message']); + $this->assertSame('Hello ' . MaskConstants::MASK_GENERIC, $result[TestConstants::FIELD_MESSAGE]); $this->assertSame(TestConstants::MASK_EMAIL_BRACKETS, $result['context'][TestConstants::CONTEXT_EMAIL]); $this->assertSame('JOHN', $result['context']['name']); } @@ -235,12 +235,12 @@ final class MaskingOrchestratorTest extends TestCase [], null, 100, - ['integer' => '[INT]'] + ['integer' => TestConstants::MASK_INT_BRACKETS] ); $result = $orchestrator->processContext(['count' => 42]); - $this->assertSame('[INT]', $result['count']); + $this->assertSame(TestConstants::MASK_INT_BRACKETS, $result['count']); } public function testProcessContextWithRemoveConfig(): void diff --git a/tests/Plugins/AbstractMaskingPluginTest.php b/tests/Plugins/AbstractMaskingPluginTest.php index 1f36fb9..e8c0837 100644 --- a/tests/Plugins/AbstractMaskingPluginTest.php +++ b/tests/Plugins/AbstractMaskingPluginTest.php @@ -8,6 +8,7 @@ use Ivuorinen\MonologGdprFilter\Contracts\MaskingPluginInterface; use Ivuorinen\MonologGdprFilter\Plugins\AbstractMaskingPlugin; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Tests\TestConstants; #[CoversClass(AbstractMaskingPlugin::class)] final class AbstractMaskingPluginTest extends TestCase @@ -92,7 +93,7 @@ final class AbstractMaskingPluginTest extends TestCase } }; - $message = 'test message'; + $message = TestConstants::MESSAGE_TEST_LOWERCASE; $result = $plugin->preProcessMessage($message); $this->assertSame($message, $result); @@ -107,7 +108,7 @@ final class AbstractMaskingPluginTest extends TestCase } }; - $message = 'test message'; + $message = TestConstants::MESSAGE_TEST_LOWERCASE; $result = $plugin->postProcessMessage($message); $this->assertSame($message, $result); @@ -185,13 +186,13 @@ final class AbstractMaskingPluginTest extends TestCase public function getPatterns(): array { - return ['/secret/' => '[REDACTED]']; + return [TestConstants::PATTERN_SECRET => TestConstants::MASK_REDACTED_BRACKETS]; } }; $patterns = $plugin->getPatterns(); - $this->assertArrayHasKey('/secret/', $patterns); - $this->assertSame('[REDACTED]', $patterns['/secret/']); + $this->assertArrayHasKey(TestConstants::PATTERN_SECRET, $patterns); + $this->assertSame(TestConstants::MASK_REDACTED_BRACKETS, $patterns[TestConstants::PATTERN_SECRET]); } } diff --git a/tests/Recovery/RecoveryResultTest.php b/tests/Recovery/RecoveryResultTest.php index 90dd901..2d988c4 100644 --- a/tests/Recovery/RecoveryResultTest.php +++ b/tests/Recovery/RecoveryResultTest.php @@ -41,9 +41,9 @@ final class RecoveryResultTest extends TestCase public function testFallbackCreation(): void { $error = ErrorContext::create('TestError', 'Failed to mask'); - $result = RecoveryResult::fallback('[REDACTED]', 3, $error, 50.0); + $result = RecoveryResult::fallback(TestConstants::MASK_REDACTED_BRACKETS, 3, $error, 50.0); - $this->assertSame('[REDACTED]', $result->value); + $this->assertSame(TestConstants::MASK_REDACTED_BRACKETS, $result->value); $this->assertSame(RecoveryResult::OUTCOME_FALLBACK, $result->outcome); $this->assertSame(3, $result->attempts); $this->assertSame($error, $result->lastError); diff --git a/tests/Recovery/RetryStrategyTest.php b/tests/Recovery/RetryStrategyTest.php index d5d72f8..04831d2 100644 --- a/tests/Recovery/RetryStrategyTest.php +++ b/tests/Recovery/RetryStrategyTest.php @@ -286,7 +286,7 @@ final class RetryStrategyTest extends TestCase $auditLogs[] = [ 'path' => $path, 'original' => $original, - 'masked' => $masked + TestConstants::DATA_MASKED => $masked ]; }; diff --git a/tests/RecursiveProcessorTest.php b/tests/RecursiveProcessorTest.php index a65fe85..4c3b5f6 100644 --- a/tests/RecursiveProcessorTest.php +++ b/tests/RecursiveProcessorTest.php @@ -115,7 +115,7 @@ final class RecursiveProcessorTest extends TestCase $dataTypeMasker = new DataTypeMasker([]); $processor = new RecursiveProcessor($regexProcessor, $dataTypeMasker, null, 10); - $data = ['field1' => 'secret data', 'field2' => TestConstants::DATA_PUBLIC]; + $data = ['field1' => TestConstants::MESSAGE_SECRET_DATA, 'field2' => TestConstants::DATA_PUBLIC]; $result = $processor->processStandardArray($data, 0); $this->assertSame('*** data', $result['field1']); @@ -128,7 +128,7 @@ final class RecursiveProcessorTest extends TestCase $dataTypeMasker = new DataTypeMasker([]); $processor = new RecursiveProcessor($regexProcessor, $dataTypeMasker, null, 10); - $result = $processor->processValue('test string', 0); + $result = $processor->processValue(TestConstants::MESSAGE_TEST_STRING, 0); $this->assertSame('*** string', $result); } @@ -158,7 +158,7 @@ final class RecursiveProcessorTest extends TestCase public function testProcessStringValueWithRegexMatch(): void { - $regexProcessor = fn(string $val): string => str_replace(TestConstants::CONTEXT_PASSWORD, '[REDACTED]', $val); + $regexProcessor = fn(string $val): string => str_replace(TestConstants::CONTEXT_PASSWORD, TestConstants::MASK_REDACTED_BRACKETS, $val); $dataTypeMasker = new DataTypeMasker([]); $processor = new RecursiveProcessor($regexProcessor, $dataTypeMasker, null, 10); @@ -198,7 +198,7 @@ final class RecursiveProcessorTest extends TestCase $dataTypeMasker = new DataTypeMasker([]); $processor = new RecursiveProcessor($regexProcessor, $dataTypeMasker, null, 10); - $result = $processor->processArrayValue(['key' => 'secret data'], 0); + $result = $processor->processArrayValue(['key' => TestConstants::MESSAGE_SECRET_DATA], 0); $this->assertIsArray($result); $this->assertSame('*** data', $result['key']); diff --git a/tests/RegexMaskProcessorTest.php b/tests/RegexMaskProcessorTest.php index 99fddfb..988a4ca 100644 --- a/tests/RegexMaskProcessorTest.php +++ b/tests/RegexMaskProcessorTest.php @@ -40,7 +40,7 @@ class RegexMaskProcessorTest extends TestCase "/\b\d{6}[-+A]?\d{3}[A-Z]\b/u" => Mask::MASK_MASKED, ]; $fieldPaths = [ - "user.ssn" => self::GDPR_REPLACEMENT, + TestConstants::FIELD_USER_SSN => self::GDPR_REPLACEMENT, "order.total" => FieldMaskConfig::useProcessorPatterns(), ]; $this->processor = new GdprProcessor($patterns, $fieldPaths); @@ -49,7 +49,7 @@ class RegexMaskProcessorTest extends TestCase public function testRemoveFieldRemovesKey(): void { $patterns = DefaultPatterns::get(); - $fieldPaths = ["user.ssn" => FieldMaskConfig::remove()]; + $fieldPaths = [TestConstants::FIELD_USER_SSN => FieldMaskConfig::remove()]; $processor = new GdprProcessor($patterns, $fieldPaths); $record = $this->logEntry()->with( message: "Remove SSN", @@ -177,7 +177,7 @@ class RegexMaskProcessorTest extends TestCase foreach ($testHetu as $hetu) { $record = $this->logEntry()->with(message: 'ID: ' . $hetu); $result = ($this->processor)($record)->toArray(); - $this->assertSame("ID: " . Mask::MASK_MASKED, $result["message"]); + $this->assertSame("ID: " . Mask::MASK_MASKED, $result[TestConstants::FIELD_MESSAGE]); } } @@ -208,7 +208,7 @@ class RegexMaskProcessorTest extends TestCase context: ["user" => ["ssn" => "not-a-hetu"]], ); $result = ($this->processor)($record)->toArray(); - $this->assertSame("No sensitive data here", $result["message"]); + $this->assertSame("No sensitive data here", $result[TestConstants::FIELD_MESSAGE]); $this->assertSame(self::GDPR_REPLACEMENT, $result["context"]["user"]["ssn"]); } diff --git a/tests/RegressionTests/ComprehensiveValidationTest.php b/tests/RegressionTests/ComprehensiveValidationTest.php index 870845e..30847bc 100644 --- a/tests/RegressionTests/ComprehensiveValidationTest.php +++ b/tests/RegressionTests/ComprehensiveValidationTest.php @@ -126,9 +126,6 @@ class ComprehensiveValidationTest extends TestCase $this->assertInstanceOf(LogRecord::class, $result); $this->assertArrayHasKey('test_value', $result->context); - - // Log successful processing for each type - error_log('✅ Successfully processed PHP type: ' . $typeName); } $this->assertCount( @@ -158,7 +155,6 @@ class ComprehensiveValidationTest extends TestCase $rateLimiter->isAllowed('memory_test_key_' . $i); } - memory_get_usage(true); $initialStats = RateLimiter::getMemoryStats(); // Phase 2: Wait for cleanup window and trigger cleanup @@ -196,12 +192,6 @@ class ComprehensiveValidationTest extends TestCase $cleanupStats['total_keys'], 'Keys should not accumulate indefinitely' ); - - error_log(sprintf( - '✅ Memory management working: Keys before=%d, after=%d', - $initialStats['total_keys'], - $cleanupStats['total_keys'] - )); } /** @@ -226,50 +216,27 @@ class ComprehensiveValidationTest extends TestCase ]; $caughtCount = 0; - $totalPatterns = count($definitelyDangerousPatterns) + count($possiblyDangerousPatterns); // Test definitely dangerous patterns - foreach ($definitelyDangerousPatterns as $pattern => $description) { + foreach (array_keys($definitelyDangerousPatterns) as $pattern) { try { PatternValidator::validateAll([sprintf('/%s/', $pattern) => TestConstants::DATA_MASKED]); - error_log(sprintf( - '⚠️ Pattern not caught: %s (%s)', - $pattern, - $description - )); } catch (Throwable) { $caughtCount++; - error_log(sprintf( - '✅ Caught dangerous pattern: %s (%s)', - $pattern, - $description - )); } } // Test possibly dangerous patterns (implementation may vary) - foreach ($possiblyDangerousPatterns as $pattern => $description) { + foreach (array_keys($possiblyDangerousPatterns) as $pattern) { try { PatternValidator::validateAll([sprintf('/%s/', $pattern) => TestConstants::DATA_MASKED]); - error_log(sprintf( - 'ℹ️ Pattern allowed: %s (%s)', - $pattern, - $description - )); } catch (Throwable) { $caughtCount++; - error_log(sprintf( - '✅ Caught potentially dangerous pattern: %s (%s)', - $pattern, - $description - )); } } // At least some dangerous patterns should be caught $this->assertGreaterThan(0, $caughtCount, 'ReDoS protection should catch at least some dangerous patterns'); - - error_log(sprintf('✅ ReDoS protection caught %d/%d dangerous patterns', $caughtCount, $totalPatterns)); } /** @@ -367,17 +334,10 @@ class ComprehensiveValidationTest extends TestCase } if ($sensitiveTermsFound !== []) { - error_log(sprintf( - "⚠️ Scenario '%s': Sensitive terms still present: ", - $scenario - ) . implode(', ', $sensitiveTermsFound)); - error_log( - ' Full message: ' . $loggedMessage - ); - } else { - error_log(sprintf( - "✅ Scenario '%s': No sensitive terms found in sanitized message", - $scenario + $this->fail(sprintf( + "Scenario '%s': %d sensitive term(s) still present in masked output", + $scenario, + count($sensitiveTermsFound) )); } @@ -424,8 +384,6 @@ class ComprehensiveValidationTest extends TestCase if ($json === false) { $this->fail('RateLimiter::getMemoryStats() returned false'); } - - error_log("✅ Rate limiter statistics: " . $json); } /** @@ -484,19 +442,8 @@ class ComprehensiveValidationTest extends TestCase $memoryIncrease, 'Memory usage should be reasonable for ' . $name ); - - error_log(sprintf( - "✅ Safely processed extreme value '%s' in %ss using %d bytes", - $name, - $processingTime, - $memoryIncrease - )); } catch (Throwable $e) { // Some extreme values might cause controlled exceptions - error_log(sprintf( - "ℹ️ Extreme value '%s' caused controlled exception: ", - $name - ) . $e->getMessage()); $this->assertInstanceOf(Throwable::class, $e); } } @@ -528,8 +475,8 @@ class ComprehensiveValidationTest extends TestCase $processor = $this->createProcessor( patterns: [ '/\b\d{3}-\d{2}-\d{4}\b/' => MaskConstants::MASK_USSSN, - '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/' => MaskConstants::MASK_EMAIL, - '/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/' => MaskConstants::MASK_CC, + TestConstants::PATTERN_EMAIL_SIMPLE => MaskConstants::MASK_EMAIL, + TestConstants::PATTERN_CREDIT_CARD => MaskConstants::MASK_CC, ], fieldPaths: [ TestConstants::FIELD_USER_PASSWORD => FieldMaskConfig::remove(), @@ -618,11 +565,6 @@ class ComprehensiveValidationTest extends TestCase // Rate limiter should provide stats $stats = $rateLimitedLogger->getRateLimitStats(); $this->assertIsArray($stats); - - error_log( - "✅ Complete integration test passed with " - . count($this->auditLog) . " audit log entries" - ); } /** @@ -646,9 +588,6 @@ class ComprehensiveValidationTest extends TestCase PatternValidator::clearCache(); RateLimiter::clearAll(); - // Log final validation summary - error_log("🎯 Comprehensive validation completed successfully"); - parent::tearDown(); } } diff --git a/tests/RegressionTests/CriticalBugRegressionTest.php b/tests/RegressionTests/CriticalBugRegressionTest.php index 910d7e7..b7e3753 100644 --- a/tests/RegressionTests/CriticalBugRegressionTest.php +++ b/tests/RegressionTests/CriticalBugRegressionTest.php @@ -84,7 +84,7 @@ class CriticalBugRegressionTest extends TestCase $testCases = [ 'integer' => 42, 'double' => 3.14, - 'string' => 'test string', + 'string' => TestConstants::MESSAGE_TEST_STRING, 'boolean_true' => true, 'boolean_false' => false, 'null' => null, @@ -378,7 +378,7 @@ class CriticalBugRegressionTest extends TestCase { $safePatterns = [ '/\b\d{3}-\d{2}-\d{4}\b/' => 'SSN', - '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/' => 'EMAIL', + TestConstants::PATTERN_EMAIL_SIMPLE => 'EMAIL', '/\b\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b/' => 'CREDIT_CARD', '/\+?1?[-.\s]?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})/' => 'PHONE', ]; @@ -467,23 +467,6 @@ class CriticalBugRegressionTest extends TestCase // Note: Current implementation may not fully sanitize all patterns $this->assertStringContainsString('Rule error:', (string) $errorMessage); - // Test that at least some sanitization occurs (implementation-dependent) - $containsSensitiveInfo = false; - $sensitiveTerms = ['password=secret123', 'user=secret_user', 'host=sensitive.db.com']; - foreach ($sensitiveTerms as $term) { - if (str_contains((string) $errorMessage, $term)) { - $containsSensitiveInfo = true; - break; - } - } - - // If sensitive info is still present, log a warning for future improvement - if ($containsSensitiveInfo) { - error_log( - "Warning: Error message sanitization may need improvement: " . $errorMessage - ); - } - // For now, just ensure the error was logged properly $this->assertNotEmpty($errorMessage); } diff --git a/tests/RegressionTests/SecurityRegressionTest.php b/tests/RegressionTests/SecurityRegressionTest.php index 79f8a21..3feeb15 100644 --- a/tests/RegressionTests/SecurityRegressionTest.php +++ b/tests/RegressionTests/SecurityRegressionTest.php @@ -74,8 +74,8 @@ class SecurityRegressionTest extends TestCase { $redosPatterns = [ // Nested quantifiers - classic ReDoS - '/^(a+)+$/', - '/^(a*)*$/', + TestConstants::PATTERN_REDOS_VULNERABLE, + TestConstants::PATTERN_REDOS_NESTED_STAR, '/^(a+)*$/', // Alternation with overlapping @@ -124,8 +124,8 @@ class SecurityRegressionTest extends TestCase $legitimatePatterns = [ // Common GDPR patterns '/\b\d{3}-\d{2}-\d{4}\b/' => 'SSN', - '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/' => 'EMAIL', - '/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/' => 'CREDIT_CARD', + TestConstants::PATTERN_EMAIL_SIMPLE => MaskConstants::MASK_EMAIL, + TestConstants::PATTERN_CREDIT_CARD => 'CREDIT_CARD', '/\+?1?[-.\s]?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})/' => 'PHONE', '/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/' => 'IP_ADDRESS', diff --git a/tests/Retention/RetentionPolicyTest.php b/tests/Retention/RetentionPolicyTest.php index 71f6ec0..9573161 100644 --- a/tests/Retention/RetentionPolicyTest.php +++ b/tests/Retention/RetentionPolicyTest.php @@ -7,6 +7,7 @@ namespace Tests\Retention; use Ivuorinen\MonologGdprFilter\Retention\RetentionPolicy; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Tests\TestConstants; #[CoversClass(RetentionPolicy::class)] final class RetentionPolicyTest extends TestCase @@ -48,9 +49,9 @@ final class RetentionPolicyTest extends TestCase public function testGetFieldsCustom(): void { - $policy = new RetentionPolicy('test', 30, RetentionPolicy::ACTION_DELETE, ['email', 'phone']); + $policy = new RetentionPolicy('test', 30, RetentionPolicy::ACTION_DELETE, [TestConstants::CONTEXT_EMAIL, 'phone']); - $this->assertSame(['email', 'phone'], $policy->getFields()); + $this->assertSame([TestConstants::CONTEXT_EMAIL, 'phone'], $policy->getFields()); } public function testIsWithinRetentionRecent(): void @@ -119,12 +120,12 @@ final class RetentionPolicyTest extends TestCase public function testAnonymizeFactory(): void { - $policy = RetentionPolicy::anonymize('user_data', 90, ['email', 'name']); + $policy = RetentionPolicy::anonymize('user_data', 90, [TestConstants::CONTEXT_EMAIL, 'name']); $this->assertSame('user_data', $policy->getName()); $this->assertSame(90, $policy->getRetentionDays()); $this->assertSame(RetentionPolicy::ACTION_ANONYMIZE, $policy->getAction()); - $this->assertSame(['email', 'name'], $policy->getFields()); + $this->assertSame([TestConstants::CONTEXT_EMAIL, 'name'], $policy->getFields()); } public function testActionConstants(): void diff --git a/tests/SecuritySanitizerTest.php b/tests/SecuritySanitizerTest.php index f162513..58c5af1 100644 --- a/tests/SecuritySanitizerTest.php +++ b/tests/SecuritySanitizerTest.php @@ -6,6 +6,7 @@ namespace Tests; use Ivuorinen\MonologGdprFilter\MaskConstants; use Ivuorinen\MonologGdprFilter\SecuritySanitizer; +use Tests\TestConstants; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; @@ -314,10 +315,10 @@ class SecuritySanitizerTest extends TestCase #[Test] public function preservesPublicIpAddresses(): void { - $message = 'External server at 8.8.8.8 responded'; + $message = 'External server at ' . TestConstants::IP_ADDRESS_PUBLIC . ' responded'; $sanitized = SecuritySanitizer::sanitizeErrorMessage($message); - $this->assertStringContainsString('8.8.8.8', $sanitized); + $this->assertStringContainsString(TestConstants::IP_ADDRESS_PUBLIC, $sanitized); } #[Test] diff --git a/tests/SerializedDataProcessorTest.php b/tests/SerializedDataProcessorTest.php index f2d3d40..718377b 100644 --- a/tests/SerializedDataProcessorTest.php +++ b/tests/SerializedDataProcessorTest.php @@ -43,7 +43,7 @@ final class SerializedDataProcessorTest extends TestCase { $processor = $this->createProcessor(); - $message = 'User data: {"email":"' . TestConstants::EMAIL_JOHN . '","name":"John"}'; + $message = 'User data: {"' . TestConstants::CONTEXT_EMAIL . '":"' . TestConstants::EMAIL_JOHN . '","name":"' . TestConstants::NAME_FIRST . '"}'; $result = $processor->process($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -54,7 +54,7 @@ final class SerializedDataProcessorTest extends TestCase { $processor = $this->createProcessor(); - $message = 'Data: {"id":123,"email":"' . TestConstants::EMAIL_TEST . '"}'; + $message = 'Data: {"id":123,"' . TestConstants::CONTEXT_EMAIL . '":"' . TestConstants::EMAIL_TEST . '"}'; $result = $processor->process($message); // Should still be valid JSON in the message @@ -70,7 +70,7 @@ final class SerializedDataProcessorTest extends TestCase { $processor = $this->createProcessor(); - $message = 'User: {"user":{"contact":{"email":"' . TestConstants::EMAIL_TEST . '"}}}'; + $message = 'User: {"user":{"contact":{"' . TestConstants::CONTEXT_EMAIL . '":"' . TestConstants::EMAIL_TEST . '"}}}'; $result = $processor->process($message); $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); @@ -83,8 +83,8 @@ final class SerializedDataProcessorTest extends TestCase $printROutput = 'Array ( - [name] => John Doe - [email] => ' . TestConstants::EMAIL_JOHN . ' + [name] => ' . TestConstants::NAME_FULL . ' + [' . TestConstants::CONTEXT_EMAIL . '] => ' . TestConstants::EMAIL_JOHN . ' [age] => 30 )'; @@ -92,7 +92,7 @@ final class SerializedDataProcessorTest extends TestCase $this->assertStringContainsString(MaskConstants::MASK_EMAIL, $result); $this->assertStringNotContainsString(TestConstants::EMAIL_JOHN, $result); - $this->assertStringContainsString('John Doe', $result); // Name not masked + $this->assertStringContainsString(TestConstants::NAME_FULL, $result); // Name not masked } public function testProcessPrintROutputWithNestedArrays(): void @@ -119,8 +119,8 @@ PRINT_R; $processor = $this->createProcessor(); $varExportOutput = "array ( - 'name' => 'John Doe', - 'email' => '" . TestConstants::EMAIL_JOHN . "', + 'name' => '" . TestConstants::NAME_FULL . "', + '" . TestConstants::CONTEXT_EMAIL . "' => '" . TestConstants::EMAIL_JOHN . "', 'active' => true, )"; @@ -134,7 +134,7 @@ PRINT_R; { $processor = $this->createProcessor(); - $data = ['email' => TestConstants::EMAIL_TEST, 'name' => 'Test']; + $data = [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST, 'name' => 'Test']; $serialized = serialize($data); $result = $processor->process($serialized); @@ -162,7 +162,7 @@ PRINT_R; { $processor = $this->createProcessor(); - $message = 'Log entry: User {"email":"' . TestConstants::EMAIL_TEST . '"} performed action'; + $message = 'Log entry: User {"' . TestConstants::CONTEXT_EMAIL . '":"' . TestConstants::EMAIL_TEST . '"} performed action'; $result = $processor->process($message); $this->assertStringContainsString('Log entry: User', $result); @@ -179,7 +179,7 @@ PRINT_R; $processor = $this->createProcessor($auditLogger); - $processor->process('{"email":"' . TestConstants::EMAIL_TEST . '"}'); + $processor->process('{"' . TestConstants::CONTEXT_EMAIL . '":"' . TestConstants::EMAIL_TEST . '"}'); $this->assertNotEmpty($logs); $this->assertStringContainsString('json', $logs[0]['path']); @@ -195,7 +195,7 @@ PRINT_R; $processor = $this->createProcessor(); $processor->setAuditLogger($auditLogger); - $processor->process('{"email":"' . TestConstants::EMAIL_TEST . '"}'); + $processor->process('{"' . TestConstants::CONTEXT_EMAIL . '":"' . TestConstants::EMAIL_TEST . '"}'); $this->assertNotEmpty($logs); } @@ -214,7 +214,7 @@ PRINT_R; { $processor = $this->createProcessor(); - $message = 'Users: [{"email":"a@example.com"},{"email":"b@example.com"}]'; + $message = 'Users: [{"' . TestConstants::CONTEXT_EMAIL . '":"a@example.com"},{"' . TestConstants::CONTEXT_EMAIL . '":"b@example.com"}]'; $result = $processor->process($message); $this->assertStringNotContainsString('a@example.com', $result); @@ -237,7 +237,7 @@ PRINT_R; $processor = $this->createProcessor(); $varExportOutput = 'array ( - "email" => "' . TestConstants::EMAIL_JOHN . '", + "' . TestConstants::CONTEXT_EMAIL . '" => "' . TestConstants::EMAIL_JOHN . '", )'; $result = $processor->process($varExportOutput); @@ -249,7 +249,7 @@ PRINT_R; { $processor = $this->createProcessor(); - $message = 'JSON: {"email":"a@example.com"} and serialized: s:16:"b@example.com";'; + $message = 'JSON: {"' . TestConstants::CONTEXT_EMAIL . '":"a@example.com"} and serialized: s:16:"b@example.com";'; $result = $processor->process($message); $this->assertStringNotContainsString('a@example.com', $result); @@ -258,13 +258,13 @@ PRINT_R; public function testProcessWithCustomMasker(): void { - $customMasker = fn(string $value): string => str_replace('secret', '[REDACTED]', $value); + $customMasker = fn(string $value): string => str_replace('secret', TestConstants::MASK_REDACTED_BRACKETS, $value); $processor = new SerializedDataProcessor($customMasker); $message = '{"data":"this is secret information"}'; $result = $processor->process($message); - $this->assertStringContainsString('[REDACTED]', $result); + $this->assertStringContainsString(TestConstants::MASK_REDACTED_BRACKETS, $result); $this->assertStringNotContainsString('secret', $result); } } diff --git a/tests/Strategies/AbstractMaskingStrategyTest.php b/tests/Strategies/AbstractMaskingStrategyTest.php index a9bc5d1..51392ce 100644 --- a/tests/Strategies/AbstractMaskingStrategyTest.php +++ b/tests/Strategies/AbstractMaskingStrategyTest.php @@ -58,7 +58,7 @@ final class AbstractMaskingStrategyTest extends TestCase */ public function getName(): string { - return 'Test Strategy'; + return TestConstants::STRATEGY_TEST; } /** @@ -123,8 +123,8 @@ final class AbstractMaskingStrategyTest extends TestCase #[Test] public function valueToStringConvertsStringAsIs(): void { - $result = $this->strategy->testValueToString('test string'); - $this->assertSame('test string', $result); + $result = $this->strategy->testValueToString(TestConstants::MESSAGE_TEST_STRING); + $this->assertSame(TestConstants::MESSAGE_TEST_STRING, $result); } #[Test] @@ -159,7 +159,7 @@ final class AbstractMaskingStrategyTest extends TestCase public function valueToStringConvertsArray(): void { $result = $this->strategy->testValueToString(['key' => 'value']); - $this->assertSame('{"key":"value"}', $result); + $this->assertSame(TestConstants::JSON_KEY_VALUE, $result); } #[Test] @@ -256,7 +256,7 @@ final class AbstractMaskingStrategyTest extends TestCase $conditions = [ 'level' => 'Error', 'channel' => 'test-channel', - 'message' => TestConstants::MESSAGE_TEST_LOWERCASE, + TestConstants::FIELD_MESSAGE => TestConstants::MESSAGE_TEST_LOWERCASE, TestConstants::CONTEXT_USER_ID => 123, ]; @@ -323,7 +323,7 @@ final class AbstractMaskingStrategyTest extends TestCase public function generateValuePreviewHandlesNonStringValues(): void { $preview = $this->strategy->testGenerateValuePreview(['key' => 'value']); - $this->assertSame('{"key":"value"}', $preview); + $this->assertSame(TestConstants::JSON_KEY_VALUE, $preview); } #[Test] @@ -383,8 +383,8 @@ final class AbstractMaskingStrategyTest extends TestCase #[Test] public function preserveValueTypeConvertsBackToArray(): void { - $result = $this->strategy->testPreserveValueType(['original' => 'value'], '{"masked":"data"}'); - $this->assertSame(['masked' => 'data'], $result); + $result = $this->strategy->testPreserveValueType(['original' => 'value'], '{"' . TestConstants::DATA_MASKED . '":"data"}'); + $this->assertSame([TestConstants::DATA_MASKED => 'data'], $result); $this->assertIsArray($result); } @@ -392,10 +392,10 @@ final class AbstractMaskingStrategyTest extends TestCase public function preserveValueTypeConvertsBackToObject(): void { $original = (object) ['original' => 'value']; - $result = $this->strategy->testPreserveValueType($original, '{"masked":"data"}'); + $result = $this->strategy->testPreserveValueType($original, '{"' . TestConstants::DATA_MASKED . '":"data"}'); $this->assertIsObject($result); - $this->assertEquals((object) ['masked' => 'data'], $result); + $this->assertEquals((object) [TestConstants::DATA_MASKED => 'data'], $result); } #[Test] diff --git a/tests/Strategies/CallbackMaskingStrategyTest.php b/tests/Strategies/CallbackMaskingStrategyTest.php index 6a03cba..99f6af8 100644 --- a/tests/Strategies/CallbackMaskingStrategyTest.php +++ b/tests/Strategies/CallbackMaskingStrategyTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Tests\Strategies; use Ivuorinen\MonologGdprFilter\Exceptions\MaskingOperationFailedException; +use Ivuorinen\MonologGdprFilter\MaskConstants; use Ivuorinen\MonologGdprFilter\Exceptions\RuleExecutionException; use Ivuorinen\MonologGdprFilter\Strategies\CallbackMaskingStrategy; use PHPUnit\Framework\TestCase; @@ -23,9 +24,9 @@ final class CallbackMaskingStrategyTest extends TestCase public function testBasicConstruction(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; - $strategy = new CallbackMaskingStrategy('user.email', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_EMAIL, $callback); - $this->assertSame('user.email', $strategy->getFieldPath()); + $this->assertSame(TestConstants::FIELD_USER_EMAIL, $strategy->getFieldPath()); $this->assertTrue($strategy->isExactMatch()); $this->assertSame(50, $strategy->getPriority()); } @@ -33,10 +34,10 @@ final class CallbackMaskingStrategyTest extends TestCase public function testMaskWithSimpleCallback(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; - $strategy = new CallbackMaskingStrategy('user.email', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_EMAIL, $callback); $record = $this->createLogRecord(); - $result = $strategy->mask('john@example.com', 'user.email', $record); + $result = $strategy->mask(TestConstants::EMAIL_JOHN, TestConstants::FIELD_USER_EMAIL, $record); $this->assertSame(TestConstants::MASK_MASKED_BRACKETS, $result); } @@ -44,10 +45,10 @@ final class CallbackMaskingStrategyTest extends TestCase public function testMaskWithTransformingCallback(): void { $callback = fn(mixed $value): string => strtoupper((string) $value); - $strategy = new CallbackMaskingStrategy('user.name', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_NAME, $callback); $record = $this->createLogRecord(); - $result = $strategy->mask('john', 'user.name', $record); + $result = $strategy->mask('john', TestConstants::FIELD_USER_NAME, $record); $this->assertSame('JOHN', $result); } @@ -57,27 +58,27 @@ final class CallbackMaskingStrategyTest extends TestCase $callback = function (): never { throw new RuleExecutionException('Callback failed'); }; - $strategy = new CallbackMaskingStrategy('user.data', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_DATA, $callback); $record = $this->createLogRecord(); $this->expectException(MaskingOperationFailedException::class); $this->expectExceptionMessage('Callback threw exception'); - $strategy->mask('value', 'user.data', $record); + $strategy->mask('value', TestConstants::FIELD_USER_DATA, $record); } public function testShouldApplyWithExactMatch(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; $strategy = new CallbackMaskingStrategy( - 'user.email', + TestConstants::FIELD_USER_EMAIL, $callback, exactMatch: true ); $record = $this->createLogRecord(); - $this->assertTrue($strategy->shouldApply('value', 'user.email', $record)); - $this->assertFalse($strategy->shouldApply('value', 'user.name', $record)); + $this->assertTrue($strategy->shouldApply('value', TestConstants::FIELD_USER_EMAIL, $record)); + $this->assertFalse($strategy->shouldApply('value', TestConstants::FIELD_USER_NAME, $record)); $this->assertFalse($strategy->shouldApply('value', 'user.email.work', $record)); } @@ -85,32 +86,32 @@ final class CallbackMaskingStrategyTest extends TestCase { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; $strategy = new CallbackMaskingStrategy( - 'user.*', + TestConstants::PATH_USER_WILDCARD, $callback, exactMatch: false ); $record = $this->createLogRecord(); - $this->assertTrue($strategy->shouldApply('value', 'user.email', $record)); - $this->assertTrue($strategy->shouldApply('value', 'user.name', $record)); + $this->assertTrue($strategy->shouldApply('value', TestConstants::FIELD_USER_EMAIL, $record)); + $this->assertTrue($strategy->shouldApply('value', TestConstants::FIELD_USER_NAME, $record)); $this->assertFalse($strategy->shouldApply('value', 'admin.email', $record)); } public function testGetName(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; - $strategy = new CallbackMaskingStrategy('user.email', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_EMAIL, $callback); $name = $strategy->getName(); $this->assertStringContainsString('Callback Masking', $name); - $this->assertStringContainsString('user.email', $name); + $this->assertStringContainsString(TestConstants::FIELD_USER_EMAIL, $name); } public function testValidate(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; - $strategy = new CallbackMaskingStrategy('user.email', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_EMAIL, $callback); $this->assertTrue($strategy->validate()); } @@ -119,7 +120,7 @@ final class CallbackMaskingStrategyTest extends TestCase { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; $strategy = new CallbackMaskingStrategy( - 'user.email', + TestConstants::FIELD_USER_EMAIL, $callback, 75, false @@ -130,7 +131,7 @@ final class CallbackMaskingStrategyTest extends TestCase $this->assertArrayHasKey('field_path', $config); $this->assertArrayHasKey('exact_match', $config); $this->assertArrayHasKey('priority', $config); - $this->assertSame('user.email', $config['field_path']); + $this->assertSame(TestConstants::FIELD_USER_EMAIL, $config['field_path']); $this->assertFalse($config['exact_match']); $this->assertSame(75, $config['priority']); } @@ -138,7 +139,7 @@ final class CallbackMaskingStrategyTest extends TestCase public function testForPathsFactoryMethod(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; - $paths = ['user.email', 'admin.email', 'contact.email']; + $paths = [TestConstants::FIELD_USER_EMAIL, 'admin.email', 'contact.email']; $strategies = CallbackMaskingStrategy::forPaths($paths, $callback); @@ -152,20 +153,20 @@ final class CallbackMaskingStrategyTest extends TestCase public function testConstantFactoryMethod(): void { - $strategy = CallbackMaskingStrategy::constant('user.ssn', '***-**-****'); + $strategy = CallbackMaskingStrategy::constant(TestConstants::FIELD_USER_SSN, MaskConstants::MASK_SSN_PATTERN); $record = $this->createLogRecord(); - $result = $strategy->mask('123-45-6789', 'user.ssn', $record); + $result = $strategy->mask(TestConstants::SSN_US, TestConstants::FIELD_USER_SSN, $record); - $this->assertSame('***-**-****', $result); + $this->assertSame(MaskConstants::MASK_SSN_PATTERN, $result); } public function testHashFactoryMethod(): void { - $strategy = CallbackMaskingStrategy::hash('user.password', 'sha256', 8); + $strategy = CallbackMaskingStrategy::hash(TestConstants::FIELD_USER_PASSWORD, 'sha256', 8); $record = $this->createLogRecord(); - $result = $strategy->mask('secret123', 'user.password', $record); + $result = $strategy->mask('secret123', TestConstants::FIELD_USER_PASSWORD, $record); $this->assertIsString($result); $this->assertSame(11, strlen($result)); @@ -174,24 +175,24 @@ final class CallbackMaskingStrategyTest extends TestCase public function testHashWithNoTruncation(): void { - $strategy = CallbackMaskingStrategy::hash('user.password', 'md5', 0); + $strategy = CallbackMaskingStrategy::hash(TestConstants::FIELD_USER_PASSWORD, 'md5', 0); $record = $this->createLogRecord(); - $result = $strategy->mask('test', 'user.password', $record); + $result = $strategy->mask('test', TestConstants::FIELD_USER_PASSWORD, $record); $this->assertSame(32, strlen((string) $result)); } public function testPartialFactoryMethod(): void { - $strategy = CallbackMaskingStrategy::partial('user.email', 2, 4); + $strategy = CallbackMaskingStrategy::partial(TestConstants::FIELD_USER_EMAIL, 2, 4); $record = $this->createLogRecord(); - $result = $strategy->mask('john@example.com', 'user.email', $record); + $result = $strategy->mask(TestConstants::EMAIL_JOHN, TestConstants::FIELD_USER_EMAIL, $record); $this->assertStringStartsWith('jo', $result); $this->assertStringEndsWith('.com', $result); - $this->assertStringContainsString('***', $result); + $this->assertStringContainsString(MaskConstants::MASK_GENERIC, $result); } public function testPartialWithShortString(): void @@ -201,7 +202,7 @@ final class CallbackMaskingStrategyTest extends TestCase $result = $strategy->mask('abc', 'user.code', $record); - $this->assertSame('***', $result); + $this->assertSame(MaskConstants::MASK_GENERIC, $result); } public function testPartialWithCustomMaskChar(): void @@ -224,29 +225,29 @@ final class CallbackMaskingStrategyTest extends TestCase return TestConstants::MASK_MASKED_BRACKETS; }; - $strategy = new CallbackMaskingStrategy('user.data', $callback); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_DATA, $callback); $record = $this->createLogRecord(); - $strategy->mask(['key' => 'value'], 'user.data', $record); + $strategy->mask(['key' => 'value'], TestConstants::FIELD_USER_DATA, $record); $this->assertSame($receivedValue, ['key' => 'value']); } public function testCallbackCanReturnNonString(): void { - $callback = fn(mixed $value): array => ['masked' => true]; - $strategy = new CallbackMaskingStrategy('user.data', $callback); + $callback = fn(mixed $value): array => [TestConstants::DATA_MASKED => true]; + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_DATA, $callback); $record = $this->createLogRecord(); - $result = $strategy->mask(['key' => 'value'], 'user.data', $record); + $result = $strategy->mask(['key' => 'value'], TestConstants::FIELD_USER_DATA, $record); - $this->assertSame(['masked' => true], $result); + $this->assertSame([TestConstants::DATA_MASKED => true], $result); } public function testCustomPriority(): void { $callback = fn(mixed $value): string => TestConstants::MASK_MASKED_BRACKETS; - $strategy = new CallbackMaskingStrategy('user.email', $callback, 100); + $strategy = new CallbackMaskingStrategy(TestConstants::FIELD_USER_EMAIL, $callback, 100); $this->assertSame(100, $strategy->getPriority()); } diff --git a/tests/Strategies/ConditionalMaskingStrategyComprehensiveTest.php b/tests/Strategies/ConditionalMaskingStrategyComprehensiveTest.php index c466e20..ba367b8 100644 --- a/tests/Strategies/ConditionalMaskingStrategyComprehensiveTest.php +++ b/tests/Strategies/ConditionalMaskingStrategyComprehensiveTest.php @@ -59,7 +59,7 @@ final class ConditionalMaskingStrategyComprehensiveTest extends TestCase public function getName(): string { - return 'Test Strategy'; + return TestConstants::STRATEGY_TEST; } public function validate(): bool diff --git a/tests/Strategies/DataTypeMaskingStrategyComprehensiveTest.php b/tests/Strategies/DataTypeMaskingStrategyComprehensiveTest.php index 0c76648..e3e169e 100644 --- a/tests/Strategies/DataTypeMaskingStrategyComprehensiveTest.php +++ b/tests/Strategies/DataTypeMaskingStrategyComprehensiveTest.php @@ -146,14 +146,14 @@ final class DataTypeMaskingStrategyComprehensiveTest extends TestCase public function testMaskWithObjectValueJsonMask(): void { - $strategy = new DataTypeMaskingStrategy(['object' => '{"masked":"data"}']); + $strategy = new DataTypeMaskingStrategy(['object' => '{"' . TestConstants::DATA_MASKED . '":"data"}']); $record = $this->createLogRecord('Test'); $obj = (object)['original' => 'value']; $result = $strategy->mask($obj, 'field', $record); - $expected = (object)['masked' => 'data']; + $expected = (object)[TestConstants::DATA_MASKED => 'data']; $this->assertEquals($expected, $result); } @@ -411,7 +411,7 @@ final class DataTypeMaskingStrategyComprehensiveTest extends TestCase 'double' => 'D', 'boolean' => '1', // Boolean uses filter_var, so '1' becomes true 'array' => '["MASKED"]', // JSON array - 'object' => '{"masked":"value"}', // JSON object + 'object' => '{"' . TestConstants::DATA_MASKED . '":"value"}', // JSON object 'NULL' => 'N', ]); @@ -422,7 +422,7 @@ final class DataTypeMaskingStrategyComprehensiveTest extends TestCase $this->assertSame('D', $strategy->mask(3.14, 'f', $record)); $this->assertTrue($strategy->mask(true, 'f', $record)); // Boolean conversion $this->assertSame(['MASKED'], $strategy->mask([], 'f', $record)); - $this->assertEquals((object)['masked' => 'value'], $strategy->mask((object)[], 'f', $record)); + $this->assertEquals((object)[TestConstants::DATA_MASKED => 'value'], $strategy->mask((object)[], 'f', $record)); $this->assertSame('N', $strategy->mask(null, 'f', $record)); } } diff --git a/tests/Strategies/DataTypeMaskingStrategyTest.php b/tests/Strategies/DataTypeMaskingStrategyTest.php index 3fb1544..8718fde 100644 --- a/tests/Strategies/DataTypeMaskingStrategyTest.php +++ b/tests/Strategies/DataTypeMaskingStrategyTest.php @@ -70,7 +70,7 @@ final class DataTypeMaskingStrategyTest extends TestCase { $strategy = new DataTypeMaskingStrategy(['string' => MaskConstants::MASK_GENERIC]); - $this->assertTrue($strategy->shouldApply('test string', 'field', $this->logRecord)); + $this->assertTrue($strategy->shouldApply(TestConstants::MESSAGE_TEST_STRING, 'field', $this->logRecord)); } #[Test] @@ -107,11 +107,11 @@ final class DataTypeMaskingStrategyTest extends TestCase #[Test] public function maskAppliesStringMask(): void { - $strategy = new DataTypeMaskingStrategy(['string' => 'REDACTED']); + $strategy = new DataTypeMaskingStrategy(['string' => TestConstants::MASK_REDACTED_PLAIN]); $result = $strategy->mask('sensitive data', 'field', $this->logRecord); - $this->assertSame('REDACTED', $result); + $this->assertSame(TestConstants::MASK_REDACTED_PLAIN, $result); } #[Test] @@ -177,7 +177,7 @@ final class DataTypeMaskingStrategyTest extends TestCase #[Test] public function maskAppliesArrayMaskJsonArray(): void { - $strategy = new DataTypeMaskingStrategy(['array' => '["masked"]']); + $strategy = new DataTypeMaskingStrategy(['array' => '["' . TestConstants::DATA_MASKED . '"]']); $result = $strategy->mask(['original'], 'field', $this->logRecord); @@ -209,13 +209,13 @@ final class DataTypeMaskingStrategyTest extends TestCase #[Test] public function maskAppliesObjectMaskJsonObject(): void { - $strategy = new DataTypeMaskingStrategy(['object' => '{"masked":"data"}']); + $strategy = new DataTypeMaskingStrategy(['object' => '{"' . TestConstants::DATA_MASKED . '":"data"}']); $obj = (object) ['original' => 'value']; $result = $strategy->mask($obj, 'field', $this->logRecord); $this->assertIsObject($result); - $this->assertEquals((object) ['masked' => 'data'], $result); + $this->assertEquals((object) [TestConstants::DATA_MASKED => 'data'], $result); } #[Test] @@ -227,7 +227,7 @@ final class DataTypeMaskingStrategyTest extends TestCase $result = $strategy->mask($obj, 'field', $this->logRecord); $this->assertIsObject($result); - $this->assertEquals((object) ['masked' => 'MASKED'], $result); + $this->assertEquals((object) [TestConstants::DATA_MASKED => 'MASKED'], $result); } #[Test] diff --git a/tests/Strategies/FieldPathMaskingStrategyEnhancedTest.php b/tests/Strategies/FieldPathMaskingStrategyEnhancedTest.php index 89f0e90..939487b 100644 --- a/tests/Strategies/FieldPathMaskingStrategyEnhancedTest.php +++ b/tests/Strategies/FieldPathMaskingStrategyEnhancedTest.php @@ -30,7 +30,7 @@ final class FieldPathMaskingStrategyEnhancedTest extends TestCase $this->expectException(MaskingOperationFailedException::class); $this->expectExceptionMessage('Regex pattern is null'); - $strategy->mask('test value', 'field', $record); + $strategy->mask(TestConstants::VALUE_TEST, 'field', $record); } public function testApplyStaticReplacementWithNullReplacement(): void diff --git a/tests/Strategies/FieldPathMaskingStrategyTest.php b/tests/Strategies/FieldPathMaskingStrategyTest.php index ac4638e..2b27104 100644 --- a/tests/Strategies/FieldPathMaskingStrategyTest.php +++ b/tests/Strategies/FieldPathMaskingStrategyTest.php @@ -138,9 +138,9 @@ final class FieldPathMaskingStrategyTest extends TestCase TestConstants::PATTERN_SSN_FORMAT, MaskConstants::MASK_SSN_PATTERN ); - $strategy = new FieldPathMaskingStrategy(['user.ssn' => $ssnConfig]); + $strategy = new FieldPathMaskingStrategy([TestConstants::FIELD_USER_SSN => $ssnConfig]); - $result = $strategy->mask(TestConstants::SSN_US, 'user.ssn', $this->logRecord); + $result = $strategy->mask(TestConstants::SSN_US, TestConstants::FIELD_USER_SSN, $this->logRecord); $this->assertSame(MaskConstants::MASK_SSN_PATTERN, $result); } @@ -149,12 +149,12 @@ final class FieldPathMaskingStrategyTest extends TestCase public function maskAppliesStaticReplacementFromConfig(): void { $strategy = new FieldPathMaskingStrategy([ - TestConstants::FIELD_USER_NAME => FieldMaskConfig::replace('[REDACTED]'), + TestConstants::FIELD_USER_NAME => FieldMaskConfig::replace(TestConstants::MASK_REDACTED_BRACKETS), ]); $result = $strategy->mask(TestConstants::NAME_FULL, TestConstants::FIELD_USER_NAME, $this->logRecord); - $this->assertSame('[REDACTED]', $result); + $this->assertSame(TestConstants::MASK_REDACTED_BRACKETS, $result); } #[Test] @@ -238,7 +238,7 @@ final class FieldPathMaskingStrategyTest extends TestCase $strategy = new FieldPathMaskingStrategy([ TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL_PATTERN, TestConstants::FIELD_USER_PASSWORD => FieldMaskConfig::remove(), - 'user.ssn' => $ssnConfig, + TestConstants::FIELD_USER_SSN => $ssnConfig, ]); $this->assertTrue($strategy->validate()); @@ -328,7 +328,7 @@ final class FieldPathMaskingStrategyTest extends TestCase public function maskHandlesMultipleReplacementsInSameValue(): void { $strategy = new FieldPathMaskingStrategy([ - 'message' => FieldMaskConfig::regexMask(TestConstants::PATTERN_SSN_FORMAT, MaskConstants::MASK_SSN_PATTERN), + TestConstants::FIELD_MESSAGE => FieldMaskConfig::regexMask(TestConstants::PATTERN_SSN_FORMAT, MaskConstants::MASK_SSN_PATTERN), ]); $input = 'SSNs: 123-45-6789 and 987-65-4321'; diff --git a/tests/Strategies/MaskingStrategiesTest.php b/tests/Strategies/MaskingStrategiesTest.php index be592ae..ab6a680 100644 --- a/tests/Strategies/MaskingStrategiesTest.php +++ b/tests/Strategies/MaskingStrategiesTest.php @@ -127,11 +127,11 @@ class MaskingStrategiesTest extends TestCase $this->assertSame(80, $strategy->getPriority()); // Test shouldApply - $this->assertTrue($strategy->shouldApply('john@example.com', TestConstants::FIELD_USER_EMAIL, $logRecord)); + $this->assertTrue($strategy->shouldApply(TestConstants::EMAIL_JOHN, TestConstants::FIELD_USER_EMAIL, $logRecord)); $this->assertFalse($strategy->shouldApply('some value', 'other.field', $logRecord)); // Test static replacement - $masked = $strategy->mask('john@example.com', TestConstants::FIELD_USER_EMAIL, $logRecord); + $masked = $strategy->mask(TestConstants::EMAIL_JOHN, TestConstants::FIELD_USER_EMAIL, $logRecord); $this->assertEquals(MaskConstants::MASK_EMAIL, $masked); // Test removal (returns null) @@ -336,7 +336,7 @@ class MaskingStrategiesTest extends TestCase #[\Override] public function getName(): string { - return 'Test Strategy'; + return TestConstants::STRATEGY_TEST; } // Expose protected methods for testing diff --git a/tests/Strategies/RegexMaskingStrategyTest.php b/tests/Strategies/RegexMaskingStrategyTest.php index 09a1ea8..9440a01 100644 --- a/tests/Strategies/RegexMaskingStrategyTest.php +++ b/tests/Strategies/RegexMaskingStrategyTest.php @@ -64,7 +64,7 @@ final class RegexMaskingStrategyTest extends TestCase $this->expectException(InvalidRegexPatternException::class); $this->expectExceptionMessage('catastrophic backtracking'); - new RegexMaskingStrategy(['/^(a+)+$/' => MaskConstants::MASK_GENERIC]); + new RegexMaskingStrategy([TestConstants::PATTERN_REDOS_VULNERABLE => MaskConstants::MASK_GENERIC]); } #[Test] @@ -124,7 +124,7 @@ final class RegexMaskingStrategyTest extends TestCase public function maskHandlesArrayValues(): void { $strategy = new RegexMaskingStrategy([ - '/"email":"[^"]+"/' => '"email":"' . MaskConstants::MASK_EMAIL_PATTERN . '"', + '/"' . TestConstants::CONTEXT_EMAIL . '":"[^"]+"/' => '"' . TestConstants::CONTEXT_EMAIL . '":"' . MaskConstants::MASK_EMAIL_PATTERN . '"', ]); $input = [TestConstants::CONTEXT_EMAIL => TestConstants::EMAIL_TEST]; @@ -208,12 +208,12 @@ final class RegexMaskingStrategyTest extends TestCase { $strategy = new RegexMaskingStrategy( patterns: [TestConstants::PATTERN_DIGITS => MaskConstants::MASK_GENERIC], - includePaths: ['user.ssn', 'user.phone'] + includePaths: [TestConstants::FIELD_USER_SSN, 'user.phone'] ); $this->assertTrue($strategy->shouldApply( TestConstants::DATA_NUMBER_STRING, - 'user.ssn', + TestConstants::FIELD_USER_SSN, $this->logRecord )); $this->assertTrue($strategy->shouldApply( @@ -236,7 +236,7 @@ final class RegexMaskingStrategyTest extends TestCase includePaths: [TestConstants::PATH_USER_WILDCARD] ); - $this->assertTrue($strategy->shouldApply(TestConstants::DATA_NUMBER_STRING, 'user.ssn', $this->logRecord)); + $this->assertTrue($strategy->shouldApply(TestConstants::DATA_NUMBER_STRING, TestConstants::FIELD_USER_SSN, $this->logRecord)); $this->assertTrue($strategy->shouldApply(TestConstants::DATA_NUMBER_STRING, 'user.phone', $this->logRecord)); $this->assertFalse($strategy->shouldApply(TestConstants::DATA_NUMBER_STRING, 'admin.id', $this->logRecord)); } @@ -277,7 +277,7 @@ final class RegexMaskingStrategyTest extends TestCase { $strategy = new RegexMaskingStrategy([ TestConstants::PATTERN_SSN_FORMAT => MaskConstants::MASK_SSN_PATTERN, - '/[a-z]+/' => 'REDACTED', + TestConstants::PATTERN_SAFE => TestConstants::MASK_REDACTED_PLAIN, ]); $this->assertTrue($strategy->validate()); @@ -297,7 +297,7 @@ final class RegexMaskingStrategyTest extends TestCase public function getConfigurationReturnsFullConfiguration(): void { $patterns = [TestConstants::PATTERN_DIGITS => MaskConstants::MASK_GENERIC]; - $includePaths = ['user.ssn']; + $includePaths = [TestConstants::FIELD_USER_SSN]; $excludePaths = ['debug.*']; $strategy = new RegexMaskingStrategy( @@ -334,7 +334,7 @@ final class RegexMaskingStrategyTest extends TestCase '/REPLACED/' => 'FINAL', ]); - $result = $strategy->mask('test value', 'field', $this->logRecord); + $result = $strategy->mask(TestConstants::VALUE_TEST, 'field', $this->logRecord); $this->assertSame('FINAL value', $result); } @@ -367,13 +367,13 @@ final class RegexMaskingStrategyTest extends TestCase public function maskHandlesMultilinePatterns(): void { $strategy = new RegexMaskingStrategy([ - '/^line\d+$/m' => 'REDACTED', + '/^line\d+$/m' => TestConstants::MASK_REDACTED_PLAIN, ]); $input = "line1\nother\nline2"; $result = $strategy->mask($input, 'field', $this->logRecord); - $this->assertStringContainsString('REDACTED', $result); + $this->assertStringContainsString(TestConstants::MASK_REDACTED_PLAIN, $result); $this->assertStringContainsString('other', $result); } } diff --git a/tests/Strategies/StrategyEdgeCasesTest.php b/tests/Strategies/StrategyEdgeCasesTest.php index 111d12f..e0029b3 100644 --- a/tests/Strategies/StrategyEdgeCasesTest.php +++ b/tests/Strategies/StrategyEdgeCasesTest.php @@ -17,6 +17,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; +use Tests\TestConstants; /** * Edge case tests for masking strategies to improve coverage. @@ -35,7 +36,7 @@ final class StrategyEdgeCasesTest extends TestCase datetime: new DateTimeImmutable(), channel: 'test', level: Level::Info, - message: 'Test message', + message: TestConstants::MESSAGE_DEFAULT, context: [], ); } @@ -61,8 +62,8 @@ final class StrategyEdgeCasesTest extends TestCase public static function redosPatternProvider(): array { return [ - 'nested plus quantifier' => ['/^(a+)+$/'], - 'nested star quantifier' => ['/^(a*)*$/'], + 'nested plus quantifier' => [TestConstants::PATTERN_REDOS_VULNERABLE], + 'nested star quantifier' => [TestConstants::PATTERN_REDOS_NESTED_STAR], 'plus with repetition' => ['/^(a+){1,10}$/'], 'star with repetition' => ['/^(a*){1,10}$/'], 'identical alternation with star' => ['/(.*|.*)x/'], @@ -76,9 +77,9 @@ final class StrategyEdgeCasesTest extends TestCase public function regexStrategySafePatternsPasses(): void { $strategy = new RegexMaskingStrategy([ - '/\d{3}-\d{2}-\d{4}/' => '[SSN]', - '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/' => '[EMAIL]', - '/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/' => '[CARD]', + TestConstants::PATTERN_SSN_FORMAT => TestConstants::MASK_SSN_BRACKETS, + TestConstants::PATTERN_EMAIL_SIMPLE => TestConstants::MASK_EMAIL_BRACKETS, + TestConstants::PATTERN_CREDIT_CARD => TestConstants::MASK_CARD_BRACKETS, ]); $this->assertInstanceOf(RegexMaskingStrategy::class, $strategy); @@ -153,7 +154,7 @@ final class StrategyEdgeCasesTest extends TestCase $result = $strategy->mask($obj, 'field', $this->logRecord); $this->assertIsObject($result); - $this->assertEquals((object) ['masked' => '{invalid json'], $result); + $this->assertEquals((object) [TestConstants::DATA_MASKED => '{invalid json'], $result); } #[Test] @@ -165,7 +166,7 @@ final class StrategyEdgeCasesTest extends TestCase $result = $strategy->mask($obj, 'field', $this->logRecord); $this->assertIsObject($result); - $this->assertEquals((object) ['masked' => '["array"]'], $result); + $this->assertEquals((object) [TestConstants::DATA_MASKED => '["array"]'], $result); } #[Test] @@ -256,7 +257,7 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyValidateWithValidStringConfig(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.email' => MaskConstants::MASK_EMAIL_PATTERN, + TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL_PATTERN, ]); $this->assertTrue($strategy->validate()); @@ -266,8 +267,8 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyValidateWithFieldMaskConfig(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.email' => FieldMaskConfig::replace(MaskConstants::MASK_EMAIL_PATTERN), - 'user.ssn' => FieldMaskConfig::remove(), + TestConstants::FIELD_USER_EMAIL => FieldMaskConfig::replace(MaskConstants::MASK_EMAIL_PATTERN), + TestConstants::FIELD_USER_SSN => FieldMaskConfig::remove(), ]); $this->assertTrue($strategy->validate()); @@ -277,7 +278,7 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyValidateWithValidRegexConfig(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.data' => FieldMaskConfig::regexMask('/\d+/', '[MASKED]'), + TestConstants::FIELD_USER_DATA => FieldMaskConfig::regexMask(TestConstants::PATTERN_DIGITS, MaskConstants::MASK_BRACKETS), ]); $this->assertTrue($strategy->validate()); @@ -338,7 +339,7 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyShouldApplyReturnsFalseForMissingPath(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.email' => MaskConstants::MASK_EMAIL_PATTERN, + TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL_PATTERN, ]); $this->assertFalse($strategy->shouldApply('value', 'other.path', $this->logRecord)); @@ -348,11 +349,11 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyShouldApplyReturnsTrueForWildcardMatch(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.*' => MaskConstants::MASK_GENERIC, + TestConstants::PATH_USER_WILDCARD => MaskConstants::MASK_GENERIC, ]); - $this->assertTrue($strategy->shouldApply('value', 'user.email', $this->logRecord)); - $this->assertTrue($strategy->shouldApply('value', 'user.name', $this->logRecord)); + $this->assertTrue($strategy->shouldApply('value', TestConstants::FIELD_USER_EMAIL, $this->logRecord)); + $this->assertTrue($strategy->shouldApply('value', TestConstants::FIELD_USER_NAME, $this->logRecord)); } #[Test] @@ -371,19 +372,19 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyMaskAppliesRegexConfig(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.ssn' => FieldMaskConfig::regexMask('/\d{3}-\d{2}-\d{4}/', '[SSN]'), + TestConstants::FIELD_USER_SSN => FieldMaskConfig::regexMask(TestConstants::PATTERN_SSN_FORMAT, TestConstants::MASK_SSN_BRACKETS), ]); - $result = $strategy->mask('SSN: 123-45-6789', 'user.ssn', $this->logRecord); + $result = $strategy->mask('SSN: 123-45-6789', TestConstants::FIELD_USER_SSN, $this->logRecord); - $this->assertSame('SSN: [SSN]', $result); + $this->assertSame(TestConstants::EXPECTED_SSN_MASKED, $result); } #[Test] public function fieldPathStrategyMaskHandlesArrayValue(): void { $strategy = new FieldPathMaskingStrategy([ - 'data' => FieldMaskConfig::regexMask('/\d+/', '[NUM]'), + 'data' => FieldMaskConfig::regexMask(TestConstants::PATTERN_DIGITS, '[NUM]'), ]); $result = $strategy->mask(['count' => '123 items'], 'data', $this->logRecord); @@ -396,7 +397,7 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyMaskReturnsValueWhenNoConfigMatch(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.email' => MaskConstants::MASK_EMAIL_PATTERN, + TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL_PATTERN, ]); $result = $strategy->mask('original', 'other.field', $this->logRecord); @@ -408,7 +409,7 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyGetNameReturnsCorrectFormat(): void { $strategy = new FieldPathMaskingStrategy([ - 'user.email' => MaskConstants::MASK_EMAIL_PATTERN, + TestConstants::FIELD_USER_EMAIL => MaskConstants::MASK_EMAIL_PATTERN, 'user.phone' => MaskConstants::MASK_PHONE, ]); @@ -421,7 +422,7 @@ final class StrategyEdgeCasesTest extends TestCase public function fieldPathStrategyGetConfigurationReturnsAllSettings(): void { $config = [ - 'user.email' => FieldMaskConfig::replace('[EMAIL]'), + TestConstants::FIELD_USER_EMAIL => FieldMaskConfig::replace(TestConstants::MASK_EMAIL_BRACKETS), ]; $strategy = new FieldPathMaskingStrategy($config); diff --git a/tests/Strategies/StrategyManagerComprehensiveTest.php b/tests/Strategies/StrategyManagerComprehensiveTest.php index 2481568..aadf802 100644 --- a/tests/Strategies/StrategyManagerComprehensiveTest.php +++ b/tests/Strategies/StrategyManagerComprehensiveTest.php @@ -122,9 +122,9 @@ final class StrategyManagerComprehensiveTest extends TestCase $manager = new StrategyManager(); $record = $this->createLogRecord('Test'); - $result = $manager->maskValue('test value', 'field', $record); + $result = $manager->maskValue(TestConstants::VALUE_TEST, 'field', $record); - $this->assertSame('test value', $result); + $this->assertSame(TestConstants::VALUE_TEST, $result); } public function testMaskValueAppliesFirstApplicableStrategy(): void @@ -137,7 +137,7 @@ final class StrategyManagerComprehensiveTest extends TestCase $manager = new StrategyManager([$lowPrio, $highPrio]); $record = $this->createLogRecord('Test'); - $result = $manager->maskValue('secret data', 'field', $record); + $result = $manager->maskValue(TestConstants::MESSAGE_SECRET_DATA, 'field', $record); // High priority strategy should be applied $this->assertStringContainsString('HIGH', $result); @@ -206,7 +206,7 @@ final class StrategyManagerComprehensiveTest extends TestCase $manager = new StrategyManager([$strategy]); $record = $this->createLogRecord('Test'); - $result = $manager->hasApplicableStrategy('secret data', 'field', $record); + $result = $manager->hasApplicableStrategy(TestConstants::MESSAGE_SECRET_DATA, 'field', $record); $this->assertTrue($result); } diff --git a/tests/Streaming/StreamingProcessorTest.php b/tests/Streaming/StreamingProcessorTest.php index f3d6e78..5990c4f 100644 --- a/tests/Streaming/StreamingProcessorTest.php +++ b/tests/Streaming/StreamingProcessorTest.php @@ -25,13 +25,13 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 10); $records = [ - ['message' => 'test message', 'context' => []], + [TestConstants::FIELD_MESSAGE => TestConstants::MESSAGE_TEST_LOWERCASE, 'context' => []], ]; $results = iterator_to_array($processor->processStream($records)); $this->assertCount(1, $results); - $this->assertSame(MaskConstants::MASK_GENERIC . ' message', $results[0]['message']); + $this->assertSame(MaskConstants::MASK_GENERIC . ' message', $results[0][TestConstants::FIELD_MESSAGE]); } public function testProcessStreamMultipleRecords(): void @@ -39,9 +39,9 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 10); $records = [ - ['message' => 'test one', 'context' => []], - ['message' => 'test two', 'context' => []], - ['message' => 'test three', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test one', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test two', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test three', 'context' => []], ]; $results = iterator_to_array($processor->processStream($records)); @@ -54,11 +54,11 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 2); $records = [ - ['message' => 'test 1', 'context' => []], - ['message' => 'test 2', 'context' => []], - ['message' => 'test 3', 'context' => []], - ['message' => 'test 4', 'context' => []], - ['message' => 'test 5', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test 1', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test 2', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test 3', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test 4', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test 5', 'context' => []], ]; $results = iterator_to_array($processor->processStream($records)); @@ -71,12 +71,12 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 10); $records = [ - ['message' => 'message', 'context' => ['key' => 'test value']], + [TestConstants::FIELD_MESSAGE => TestConstants::FIELD_MESSAGE, 'context' => ['key' => TestConstants::VALUE_TEST]], ]; $results = iterator_to_array($processor->processStream($records)); - $this->assertSame(MaskConstants::MASK_GENERIC . ' value', $results[0]['context']['key']); + $this->assertSame(MaskConstants::MASK_GENERIC . TestConstants::VALUE_SUFFIX, $results[0]['context']['key']); } public function testProcessStreamWithGenerator(): void @@ -84,9 +84,9 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 2); $generator = (function () { - yield ['message' => 'test a', 'context' => []]; - yield ['message' => 'test b', 'context' => []]; - yield ['message' => 'test c', 'context' => []]; + yield [TestConstants::FIELD_MESSAGE => 'test a', 'context' => []]; + yield [TestConstants::FIELD_MESSAGE => 'test b', 'context' => []]; + yield [TestConstants::FIELD_MESSAGE => 'test c', 'context' => []]; })(); $results = iterator_to_array($processor->processStream($generator)); @@ -104,7 +104,7 @@ final class StreamingProcessorTest extends TestCase file_put_contents($tempFile, "test line 1\ntest line 2\ntest line 3\n"); try { - $lineParser = fn(string $line): array => ['message' => $line, 'context' => []]; + $lineParser = fn(string $line): array => [TestConstants::FIELD_MESSAGE => $line, 'context' => []]; $results = []; foreach ($processor->processFile($tempFile, $lineParser) as $result) { @@ -112,7 +112,7 @@ final class StreamingProcessorTest extends TestCase } $this->assertCount(3, $results); - $this->assertStringContainsString(MaskConstants::MASK_GENERIC, $results[0]['message']); + $this->assertStringContainsString(MaskConstants::MASK_GENERIC, $results[0][TestConstants::FIELD_MESSAGE]); } finally { unlink($tempFile); } @@ -127,7 +127,7 @@ final class StreamingProcessorTest extends TestCase file_put_contents($tempFile, "test line 1\n\n\ntest line 2\n"); try { - $lineParser = fn(string $line): array => ['message' => $line, 'context' => []]; + $lineParser = fn(string $line): array => [TestConstants::FIELD_MESSAGE => $line, 'context' => []]; $results = iterator_to_array($processor->processFile($tempFile, $lineParser)); @@ -144,7 +144,7 @@ final class StreamingProcessorTest extends TestCase $this->expectException(StreamingOperationFailedException::class); $this->expectExceptionMessage('Cannot open input file for streaming:'); - iterator_to_array($processor->processFile('/nonexistent/path/file.log', fn(string $l): array => ['message' => $l, 'context' => []])); + iterator_to_array($processor->processFile('/nonexistent/path/file.log', fn(string $l): array => [TestConstants::FIELD_MESSAGE => $l, 'context' => []])); } public function testProcessToFile(): void @@ -152,15 +152,15 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 10); $records = [ - ['message' => 'test line 1', 'context' => []], - ['message' => 'test line 2', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test line 1', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test line 2', 'context' => []], ]; $outputFile = tempnam(sys_get_temp_dir(), 'gdpr_output_'); $this->assertIsString($outputFile, 'Failed to create temp file'); try { - $formatter = fn(array $record): string => $record['message']; + $formatter = fn(array $record): string => $record[TestConstants::FIELD_MESSAGE]; $count = $processor->processToFile($records, $outputFile, $formatter); $this->assertSame(2, $count); @@ -188,15 +188,33 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 10); $records = [ - ['message' => 'test masked', 'context' => []], - ['message' => 'no sensitive data', 'context' => []], - ['message' => 'another test here', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'test masked', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'no sensitive data', 'context' => []], + [TestConstants::FIELD_MESSAGE => 'another test here', 'context' => []], ]; $stats = $processor->getStatistics($records); $this->assertSame(3, $stats['processed']); - $this->assertGreaterThan(0, $stats['masked']); // At least some should be masked + $this->assertSame(2, $stats[TestConstants::DATA_MASKED]); + } + + public function testGetStatisticsDoesNotTriggerAuditLogger(): void + { + $auditCalled = false; + $auditLogger = function () use (&$auditCalled): void { + $auditCalled = true; + }; + + $processor = new StreamingProcessor($this->createOrchestrator(), 10, $auditLogger); + + $records = [ + [TestConstants::FIELD_MESSAGE => TestConstants::DATA_TEST_DATA, 'context' => []], + ]; + + $processor->getStatistics($records); + + $this->assertFalse($auditCalled); } public function testSetAuditLogger(): void @@ -209,7 +227,7 @@ final class StreamingProcessorTest extends TestCase $processor = new StreamingProcessor($this->createOrchestrator(), 1); $processor->setAuditLogger($auditLogger); - $records = [['message' => 'test', 'context' => []]]; + $records = [[TestConstants::FIELD_MESSAGE => 'test', 'context' => []]]; iterator_to_array($processor->processStream($records)); $this->assertNotEmpty($logs); @@ -235,7 +253,7 @@ final class StreamingProcessorTest extends TestCase $records = []; for ($i = 1; $i <= 500; $i++) { - $records[] = ['message' => "test record {$i}", 'context' => []]; + $records[] = [TestConstants::FIELD_MESSAGE => "test record {$i}", 'context' => []]; } $count = 0; diff --git a/tests/TestConstants.php b/tests/TestConstants.php index 90949cf..cf1deaa 100644 --- a/tests/TestConstants.php +++ b/tests/TestConstants.php @@ -145,6 +145,8 @@ final class TestConstants public const FIELD_USER_NAME = 'user.name'; public const FIELD_USER_PUBLIC = 'user.public'; public const FIELD_USER_PASSWORD = 'user.password'; + public const FIELD_USER_SSN = 'user.ssn'; + public const FIELD_USER_DATA = 'user.data'; public const FIELD_SYSTEM_LOG = 'system.log'; // Path Patterns @@ -168,20 +170,32 @@ final class TestConstants // Mask placeholders used in tests (bracketed format) public const MASK_REDACTED_BRACKETS = '[REDACTED]'; public const MASK_MASKED_BRACKETS = '[MASKED]'; + public const MASK_SECRET_BRACKETS = '[SECRET]'; + public const MASK_SSN_BRACKETS = '[SSN]'; public const MASK_EMAIL_BRACKETS = '[EMAIL]'; public const MASK_DIGITS_BRACKETS = '[DIGITS]'; public const MASK_INT_BRACKETS = '[INT]'; public const MASK_ALWAYS_THIS = '[ALWAYS_THIS]'; + public const MASK_REDACTED_PLAIN = 'REDACTED'; // Test values public const VALUE_TEST = 'test value'; public const VALUE_SUFFIX = ' value'; + // Expected output strings + public const EXPECTED_SSN_MASKED = 'SSN: [SSN]'; + + // Mask placeholders (bracketed format, additional) + public const MASK_CARD_BRACKETS = '[CARD]'; + // Additional pattern constants + public const PATTERN_EMAIL_SIMPLE = '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/'; public const PATTERN_VALID_SIMPLE = '/^test$/'; public const PATTERN_INVALID_UNCLOSED = '/unclosed'; public const PATTERN_REDOS_VULNERABLE = '/^(a+)+$/'; + public const PATTERN_REDOS_NESTED_STAR = '/^(a*)*$/'; public const PATTERN_SAFE = '/[a-z]+/'; + public const PATTERN_CREDIT_CARD = '/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/'; /** * Prevent instantiation.