Files
michaelschiemer/tests/Database/Indexing/UnusedIndexDetectorTest.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

112 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Database\Indexing\UnusedIndexDetector;
use App\Framework\Database\Indexing\IndexAnalyzer;
use App\Framework\Database\Indexing\IndexUsageTracker;
use App\Framework\Database\PdoConnection;
describe('UnusedIndexDetector', function () {
beforeEach(function () {
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
category TEXT,
price REAL,
stock INTEGER,
created_at TEXT
)
');
$pdo->exec('CREATE INDEX idx_products_category ON products(category)');
$pdo->exec('CREATE INDEX idx_products_price ON products(price)');
$pdo->exec('CREATE INDEX idx_products_stock ON products(stock)');
$pdo->exec('CREATE INDEX idx_products_category_price ON products(category, price)');
$connection = new PdoConnection($pdo, 'sqlite');
$analyzer = new IndexAnalyzer($connection);
$cache = new \App\Framework\Cache\Driver\InMemoryCache();
$usageTracker = new IndexUsageTracker($cache, $analyzer);
$this->detector = new UnusedIndexDetector($analyzer, $usageTracker);
$this->tableName = 'products';
});
it('finds unused indexes', function () {
$unusedIndexes = $this->detector->findUnusedIndexes($this->tableName);
expect($unusedIndexes)->toBeArray();
// Since we haven't tracked any usage, all non-unique indexes should be marked as unused
expect(count($unusedIndexes))->toBeGreaterThan(0);
});
it('detects duplicate indexes', function () {
// Create duplicate index in test
// (In real scenario, we'd have actual duplicates)
$duplicates = $this->detector->findDuplicateIndexes($this->tableName);
expect($duplicates)->toBeArray();
});
it('finds redundant indexes (prefix pattern)', function () {
$redundant = $this->detector->findRedundantIndexes($this->tableName);
expect($redundant)->toBeArray();
// idx_products_category is redundant with idx_products_category_price
// because category is a prefix of [category, price]
if (!empty($redundant)) {
expect($redundant[0])->toHaveKey('redundant_index');
expect($redundant[0])->toHaveKey('covered_by');
}
});
it('generates comprehensive unused index report', function () {
$report = $this->detector->getUnusedIndexReport($this->tableName);
expect($report)->toHaveKey('unused');
expect($report)->toHaveKey('duplicates');
expect($report)->toHaveKey('redundant');
expect($report)->toHaveKey('total_removable');
expect($report)->toHaveKey('estimated_space_savings');
expect($report['unused'])->toBeArray();
expect($report['total_removable'])->toBeInt();
});
it('generates DROP statements for unused indexes', function () {
$statements = $this->detector->generateDropStatements($this->tableName);
expect($statements)->toBeArray();
foreach ($statements as $statement) {
expect($statement)->toContain('DROP INDEX');
expect($statement)->toContain('ON products');
}
});
it('never suggests dropping PRIMARY or UNIQUE indexes', function () {
$unusedIndexes = $this->detector->findUnusedIndexes($this->tableName);
// Filter for any PRIMARY or UNIQUE suggestions
$primaryOrUnique = array_filter($unusedIndexes, function ($index) {
return str_contains(strtolower($index['index_name']), 'primary') ||
str_contains(strtolower($index['index_name']), 'unique');
});
expect($primaryOrUnique)->toBeEmpty();
});
it('estimates space savings correctly', function () {
$report = $this->detector->getUnusedIndexReport($this->tableName);
expect($report['estimated_space_savings'])->toBeString();
expect($report['estimated_space_savings'])->toMatch('/(MB|GB|< 1 MB)/');
});
});