Files
michaelschiemer/tests/Unit/Framework/Filesystem/FileOperationContextLoggingTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

341 lines
12 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Core\ValueObjects\FileSize;
use App\Framework\Filesystem\ValueObjects\FileOperationContext;
use App\Framework\Filesystem\ValueObjects\FileOperation;
describe('FileOperationContext Logging', function () {
// Severity Detection Tests
describe('Severity Detection', function () {
it('identifies high severity operations', function () {
$deleteContext = FileOperationContext::forOperation(
FileOperation::DELETE,
'/path/to/file.txt'
);
expect($deleteContext->isHighSeverity())->toBeTrue();
expect($deleteContext->toArray()['severity'])->toBe('high');
$moveContext = FileOperationContext::forOperationWithDestination(
FileOperation::MOVE,
'/source/file.txt',
'/dest/file.txt'
);
expect($moveContext->isHighSeverity())->toBeTrue();
$deleteDirContext = FileOperationContext::forOperation(
FileOperation::DELETE_DIRECTORY,
'/path/to/dir'
);
expect($deleteDirContext->isHighSeverity())->toBeTrue();
});
it('identifies medium severity operations', function () {
$writeContext = FileOperationContext::forWrite(
'/path/to/file.txt',
FileSize::fromBytes(1024)
);
expect($writeContext->isHighSeverity())->toBeFalse();
expect($writeContext->toArray()['severity'])->toBe('medium');
$copyContext = FileOperationContext::forOperationWithDestination(
FileOperation::COPY,
'/source/file.txt',
'/dest/file.txt'
);
expect($copyContext->toArray()['severity'])->toBe('medium');
$createDirContext = FileOperationContext::forOperation(
FileOperation::CREATE_DIRECTORY,
'/path/to/newdir'
);
expect($createDirContext->toArray()['severity'])->toBe('medium');
});
it('identifies low severity operations', function () {
$readContext = FileOperationContext::forRead(
'/path/to/file.txt',
FileSize::fromBytes(1024)
);
expect($readContext->isHighSeverity())->toBeFalse();
expect($readContext->toArray()['severity'])->toBe('low');
$listContext = FileOperationContext::forOperation(
FileOperation::LIST_DIRECTORY,
'/path/to/dir'
);
expect($listContext->toArray()['severity'])->toBe('low');
$metadataContext = FileOperationContext::forOperation(
FileOperation::GET_METADATA,
'/path/to/file.txt'
);
expect($metadataContext->toArray()['severity'])->toBe('low');
});
});
// Large Operation Detection Tests
describe('Large Operation Detection', function () {
it('identifies large operations (>10MB)', function () {
// 15MB operation - should be large
$largeWrite = FileOperationContext::forWrite(
'/path/to/large.txt',
FileSize::fromMegabytes(15)
);
expect($largeWrite->isLargeOperation())->toBeTrue();
// 50MB read - should be large
$largeRead = FileOperationContext::forRead(
'/path/to/huge.txt',
FileSize::fromMegabytes(50)
);
expect($largeRead->isLargeOperation())->toBeTrue();
});
it('does not identify small operations as large', function () {
// 1MB operation - should NOT be large
$smallWrite = FileOperationContext::forWrite(
'/path/to/small.txt',
FileSize::fromMegabytes(1)
);
expect($smallWrite->isLargeOperation())->toBeFalse();
// 5KB read - should NOT be large
$tinyRead = FileOperationContext::forRead(
'/path/to/tiny.txt',
FileSize::fromKilobytes(5)
);
expect($tinyRead->isLargeOperation())->toBeFalse();
});
it('returns false for operations without byte information', function () {
$deleteContext = FileOperationContext::forOperation(
FileOperation::DELETE,
'/path/to/file.txt'
);
expect($deleteContext->isLargeOperation())->toBeFalse();
});
});
// Context Data Completeness Tests
describe('Context Data Completeness', function () {
it('includes all relevant data in toArray()', function () {
$context = FileOperationContext::forWrite(
'/path/to/file.txt',
FileSize::fromKilobytes(150),
'user123'
);
$context = $context->withMetadata([
'source' => 'upload',
'mime_type' => 'text/plain'
]);
$array = $context->toArray();
expect($array)->toHaveKey('operation');
expect($array)->toHaveKey('operation_name');
expect($array)->toHaveKey('path');
expect($array)->toHaveKey('timestamp');
expect($array)->toHaveKey('severity');
expect($array)->toHaveKey('bytes_affected');
expect($array)->toHaveKey('bytes_affected_human');
expect($array)->toHaveKey('user_id');
expect($array)->toHaveKey('metadata');
expect($array['operation'])->toBe('write');
expect($array['operation_name'])->toBe('file.write');
expect($array['path'])->toBe('/path/to/file.txt');
expect($array['severity'])->toBe('medium');
expect($array['bytes_affected'])->toBe(153600); // 150 * 1024
expect($array['bytes_affected_human'])->toBe('150 KB'); // toHumanReadable() returns without decimals
expect($array['user_id'])->toBe('user123');
expect($array['metadata'])->toBe([
'source' => 'upload',
'mime_type' => 'text/plain'
]);
});
it('handles operation with destination', function () {
$context = FileOperationContext::forOperationWithDestination(
FileOperation::COPY,
'/source/file.txt',
'/dest/file.txt'
);
$array = $context->toArray();
expect($array)->toHaveKey('destination_path');
expect($array['destination_path'])->toBe('/dest/file.txt');
expect($array['path'])->toBe('/source/file.txt');
});
it('generates readable string representation', function () {
$context = FileOperationContext::forWrite(
'/var/www/uploads/document.pdf',
FileSize::fromKilobytes(250),
'admin'
);
$string = $context->toString();
expect($string)->toContain('Write file contents');
expect($string)->toContain('path: /var/www/uploads/document.pdf');
expect($string)->toContain('bytes: 250'); // Flexible - may be "250 KB" or "250.00 KB"
expect($string)->toContain('user: admin');
});
});
// Write Operation Detection Tests
describe('Write Operation Detection', function () {
it('correctly identifies write operations', function () {
$writeContext = FileOperationContext::forOperation(
FileOperation::WRITE,
'/path/to/file.txt'
);
expect($writeContext->isWriteOperation())->toBeTrue();
$deleteContext = FileOperationContext::forOperation(
FileOperation::DELETE,
'/path/to/file.txt'
);
expect($deleteContext->isWriteOperation())->toBeTrue();
$moveContext = FileOperationContext::forOperationWithDestination(
FileOperation::MOVE,
'/source.txt',
'/dest.txt'
);
expect($moveContext->isWriteOperation())->toBeTrue();
});
it('correctly identifies non-write operations', function () {
$readContext = FileOperationContext::forRead(
'/path/to/file.txt',
FileSize::fromBytes(100)
);
expect($readContext->isWriteOperation())->toBeFalse();
$copyContext = FileOperationContext::forOperationWithDestination(
FileOperation::COPY,
'/source.txt',
'/dest.txt'
);
expect($copyContext->isWriteOperation())->toBeFalse();
});
});
// Immutability Tests
describe('Immutability', function () {
it('withMetadata creates new instance', function () {
$original = FileOperationContext::forOperation(
FileOperation::WRITE,
'/path/to/file.txt'
);
$modified = $original->withMetadata(['key' => 'value']);
expect($original->metadata)->toBeNull();
expect($modified->metadata)->toBe(['key' => 'value']);
expect($original)->not->toBe($modified);
});
it('withUserId creates new instance', function () {
$original = FileOperationContext::forOperation(
FileOperation::DELETE,
'/path/to/file.txt'
);
$modified = $original->withUserId('user456');
expect($original->userId)->toBeNull();
expect($modified->userId)->toBe('user456');
expect($original)->not->toBe($modified);
});
it('withMetadata merges with existing metadata', function () {
$context = FileOperationContext::forOperation(
FileOperation::WRITE,
'/file.txt'
);
$context = $context->withMetadata(['a' => 1]);
$context = $context->withMetadata(['b' => 2]);
expect($context->metadata)->toBe(['a' => 1, 'b' => 2]);
});
});
// Factory Method Tests
describe('Factory Methods', function () {
it('creates context for simple operations', function () {
$context = FileOperationContext::forOperation(
FileOperation::DELETE,
'/path/to/file.txt'
);
expect($context->operation)->toBe(FileOperation::DELETE);
expect($context->path)->toBe('/path/to/file.txt');
expect($context->timestamp)->not->toBeNull();
expect($context->destinationPath)->toBeNull();
expect($context->bytesAffected)->toBeNull();
});
it('creates context for operations with destination', function () {
$context = FileOperationContext::forOperationWithDestination(
FileOperation::MOVE,
'/source/file.txt',
'/dest/file.txt'
);
expect($context->operation)->toBe(FileOperation::MOVE);
expect($context->path)->toBe('/source/file.txt');
expect($context->destinationPath)->toBe('/dest/file.txt');
expect($context->timestamp)->not->toBeNull();
});
it('creates context for write operations', function () {
$context = FileOperationContext::forWrite(
'/path/to/file.txt',
FileSize::fromKilobytes(100),
'user789'
);
expect($context->operation)->toBe(FileOperation::WRITE);
expect($context->path)->toBe('/path/to/file.txt');
expect($context->bytesAffected)->toBeInstanceOf(FileSize::class);
expect($context->bytesAffected->toBytes())->toBe(102400);
expect($context->userId)->toBe('user789');
expect($context->timestamp)->not->toBeNull();
});
it('creates context for read operations', function () {
$context = FileOperationContext::forRead(
'/path/to/file.txt',
FileSize::fromMegabytes(5)
);
expect($context->operation)->toBe(FileOperation::READ);
expect($context->path)->toBe('/path/to/file.txt');
expect($context->bytesAffected)->toBeInstanceOf(FileSize::class);
expect($context->bytesAffected->toMegabytes())->toBe(5.0);
expect($context->timestamp)->not->toBeNull();
});
});
});