- 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.
97 lines
3.4 KiB
PHP
97 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Database\Indexing\IndexAnalyzer;
|
|
use App\Framework\Database\Indexing\ValueObjects\IndexName;
|
|
use App\Framework\Database\Indexing\ValueObjects\IndexType;
|
|
use App\Framework\Database\PdoConnection;
|
|
|
|
describe('IndexAnalyzer', function () {
|
|
beforeEach(function () {
|
|
// Create in-memory SQLite database for testing
|
|
$pdo = new PDO('sqlite::memory:');
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
// Create test table with indexes
|
|
$pdo->exec('
|
|
CREATE TABLE users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
email TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
status TEXT,
|
|
created_at TEXT
|
|
)
|
|
');
|
|
|
|
$pdo->exec('CREATE INDEX idx_users_status ON users(status)');
|
|
$pdo->exec('CREATE INDEX idx_users_created_at ON users(created_at)');
|
|
$pdo->exec('CREATE INDEX idx_users_email_status ON users(email, status)');
|
|
|
|
$this->connection = new PdoConnection($pdo, 'sqlite');
|
|
$this->analyzer = new IndexAnalyzer($this->connection);
|
|
});
|
|
|
|
it('can get all indexes for a table', function () {
|
|
$indexes = $this->analyzer->getTableIndexes('users');
|
|
|
|
expect($indexes)->toBeArray();
|
|
expect(count($indexes))->toBeGreaterThan(0);
|
|
|
|
// Should have at least: PRIMARY, UNIQUE, and our custom indexes
|
|
$indexNames = array_column($indexes, 'name');
|
|
expect($indexNames)->toContain('idx_users_status');
|
|
expect($indexNames)->toContain('idx_users_created_at');
|
|
});
|
|
|
|
it('detects index usage in query', function () {
|
|
$sql = 'SELECT * FROM users WHERE status = "active"';
|
|
$analysis = $this->analyzer->analyzeQuery($sql);
|
|
|
|
expect($analysis)->toBeArray();
|
|
expect($analysis)->toHaveKey('query');
|
|
expect($analysis)->toHaveKey('indexes_used');
|
|
expect($analysis)->toHaveKey('key_type');
|
|
expect($analysis['query'])->toBe($sql);
|
|
});
|
|
|
|
it('detects composite index columns correctly', function () {
|
|
$indexes = $this->analyzer->getTableIndexes('users');
|
|
|
|
$compositeIndex = array_values(array_filter($indexes, function ($index) {
|
|
return $index['name'] === 'idx_users_email_status';
|
|
}))[0] ?? null;
|
|
|
|
expect($compositeIndex)->not->toBeNull();
|
|
expect($compositeIndex['columns'])->toBe(['email', 'status']);
|
|
});
|
|
|
|
it('identifies index types correctly', function () {
|
|
$indexes = $this->analyzer->getTableIndexes('users');
|
|
|
|
foreach ($indexes as $index) {
|
|
expect($index['type'])->toBeInstanceOf(IndexType::class);
|
|
}
|
|
});
|
|
|
|
it('marks unique indexes correctly', function () {
|
|
$indexes = $this->analyzer->getTableIndexes('users');
|
|
|
|
$uniqueIndex = array_values(array_filter($indexes, function ($index) {
|
|
return str_contains($index['name'], 'email');
|
|
}))[0] ?? null;
|
|
|
|
expect($uniqueIndex)->not->toBeNull();
|
|
expect($uniqueIndex['is_unique'])->toBeTrue();
|
|
});
|
|
|
|
it('analyzes queries without indexes', function () {
|
|
$sql = 'SELECT * FROM users WHERE name LIKE "%John%"';
|
|
$analysis = $this->analyzer->analyzeQuery($sql);
|
|
|
|
expect($analysis['indexes_used'])->toBeArray();
|
|
// SQLite might use table scan for LIKE queries
|
|
expect($analysis['key_type'])->toBeIn(['scan', 'ALL', 'index']);
|
|
});
|
|
});
|