feat: CI/CD pipeline setup complete - Ansible playbooks updated, secrets configured, workflow ready
This commit is contained in:
134
tests/debug/test-analytics-route-discovery.php
Normal file
134
tests/debug/test-analytics-route-discovery.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\Router\CompiledRoutes;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
|
||||
echo "=== Analytics Route Discovery Debug ===\n\n";
|
||||
|
||||
// Bootstrap the container
|
||||
echo "1. Bootstrapping container...\n";
|
||||
$basePath = dirname(__DIR__, 2);
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: true);
|
||||
$bootstrapper = new AppBootstrapper($basePath, $collector, $memoryMonitor);
|
||||
$container = $bootstrapper->bootstrapWorker();
|
||||
|
||||
// Get CompiledRoutes
|
||||
echo "2. Getting compiled routes...\n";
|
||||
$compiledRoutes = $container->get(CompiledRoutes::class);
|
||||
|
||||
// Get all routes
|
||||
$staticRoutes = $compiledRoutes->getStaticRoutes();
|
||||
$dynamicRoutes = $compiledRoutes->getDynamicRoutes();
|
||||
|
||||
echo " Static routes: " . count($staticRoutes) . "\n";
|
||||
echo " Dynamic routes: " . count($dynamicRoutes) . "\n\n";
|
||||
|
||||
// Search for analytics/dashboard routes
|
||||
echo "3. Searching for dashboard/analytics routes:\n";
|
||||
$found = [];
|
||||
|
||||
// Search static routes
|
||||
foreach ($staticRoutes as $path => $methodMap) {
|
||||
if (str_contains($path, 'dashboard') || str_contains($path, 'analytics')) {
|
||||
foreach ($methodMap as $method => $handler) {
|
||||
$found[] = [
|
||||
'type' => 'STATIC',
|
||||
'method' => $method,
|
||||
'path' => $path,
|
||||
'handler' => get_class($handler)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search dynamic routes
|
||||
foreach ($dynamicRoutes as $route) {
|
||||
$path = $route['path'] ?? $route['pattern'] ?? 'N/A';
|
||||
if (str_contains($path, 'dashboard') || str_contains($path, 'analytics')) {
|
||||
$method = $route['method'] ?? ($route['methods'][0] ?? 'N/A');
|
||||
$found[] = [
|
||||
'type' => 'DYNAMIC',
|
||||
'method' => $method,
|
||||
'path' => $path,
|
||||
'handler' => $route['class'] ?? 'N/A'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($found)) {
|
||||
echo " ❌ No dashboard/analytics routes found!\n\n";
|
||||
} else {
|
||||
echo " ✅ Found " . count($found) . " routes:\n";
|
||||
foreach ($found as $route) {
|
||||
echo sprintf(
|
||||
" [%s] %s %s -> %s\n",
|
||||
$route['type'],
|
||||
$route['method'],
|
||||
$route['path'],
|
||||
$route['handler']
|
||||
);
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
// Check if AnalyticsDashboard class exists
|
||||
echo "4. Class existence check:\n";
|
||||
$className = 'App\\Application\\SmartLink\\Dashboard\\AnalyticsDashboard';
|
||||
echo " Class: $className\n";
|
||||
echo " Exists: " . (class_exists($className) ? '✅ YES' : '❌ NO') . "\n\n";
|
||||
|
||||
// Check if class is in any route
|
||||
echo "5. Searching all routes for AnalyticsDashboard:\n";
|
||||
$analyticsDashboardFound = false;
|
||||
|
||||
foreach ($staticRoutes as $path => $methodMap) {
|
||||
foreach ($methodMap as $method => $handler) {
|
||||
if (get_class($handler) === $className) {
|
||||
$analyticsDashboardFound = true;
|
||||
echo " ✅ Found in static routes: [$method] $path\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($dynamicRoutes as $route) {
|
||||
if (isset($route['class']) && $route['class'] === $className) {
|
||||
$analyticsDashboardFound = true;
|
||||
$method = $route['method'] ?? 'N/A';
|
||||
$path = $route['path'] ?? $route['pattern'] ?? 'N/A';
|
||||
echo " ✅ Found in dynamic routes: [$method] $path\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!$analyticsDashboardFound) {
|
||||
echo " ❌ AnalyticsDashboard NOT found in any compiled routes!\n\n";
|
||||
}
|
||||
|
||||
// Check the Route attribute on the class
|
||||
echo "6. Checking Route attribute on AnalyticsDashboard:\n";
|
||||
$reflection = new ReflectionClass($className);
|
||||
$method = $reflection->getMethod('__invoke');
|
||||
$attributes = $method->getAttributes(\App\Framework\Attributes\Route::class);
|
||||
|
||||
if (empty($attributes)) {
|
||||
echo " ❌ No Route attributes found on __invoke method!\n";
|
||||
} else {
|
||||
echo " ✅ Found " . count($attributes) . " Route attribute(s):\n";
|
||||
foreach ($attributes as $attr) {
|
||||
$route = $attr->newInstance();
|
||||
echo " Path: " . $route->path . "\n";
|
||||
echo " Method: " . $route->method->value . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n=== End Debug ===\n";
|
||||
81
tests/debug/test-cache-warming.php
Normal file
81
tests/debug/test-cache-warming.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\Cache\Driver\FileCache;
|
||||
use App\Framework\Cache\GeneralCache;
|
||||
use App\Framework\Serializer\Php\PhpSerializer;
|
||||
use App\Framework\Cache\Warming\Strategies\CriticalPathWarmingStrategy;
|
||||
use App\Framework\Router\CompiledRoutes;
|
||||
use App\Framework\Config\Environment;
|
||||
|
||||
echo "🔍 Testing Cache Warming System\n\n";
|
||||
|
||||
// Setup
|
||||
$fileCache = new FileCache();
|
||||
$serializer = new PhpSerializer();
|
||||
$cache = new GeneralCache($fileCache, $serializer);
|
||||
|
||||
$compiledRoutes = new CompiledRoutes(
|
||||
staticRoutes: [
|
||||
'GET' => [
|
||||
'default' => [
|
||||
'/home' => null,
|
||||
'/about' => null,
|
||||
]
|
||||
]
|
||||
],
|
||||
dynamicPatterns: [
|
||||
'GET' => [
|
||||
'default' => null
|
||||
]
|
||||
],
|
||||
namedRoutes: []
|
||||
);
|
||||
|
||||
$environment = new Environment([
|
||||
'APP_ENV' => 'testing',
|
||||
'APP_DEBUG' => 'true',
|
||||
]);
|
||||
|
||||
echo "✅ Created Cache, CompiledRoutes, Environment\n\n";
|
||||
|
||||
// Create strategy
|
||||
$strategy = new CriticalPathWarmingStrategy(
|
||||
cache: $cache,
|
||||
compiledRoutes: $compiledRoutes,
|
||||
environment: $environment
|
||||
);
|
||||
|
||||
echo "✅ Created CriticalPathWarmingStrategy\n";
|
||||
echo " Name: " . $strategy->getName() . "\n";
|
||||
echo " Priority: " . $strategy->getPriority() . "\n";
|
||||
echo " Should Run: " . ($strategy->shouldRun() ? 'yes' : 'no') . "\n";
|
||||
echo " Estimated Duration: " . $strategy->getEstimatedDuration() . "s\n\n";
|
||||
|
||||
// Execute warmup
|
||||
echo "🔥 Executing warmup...\n";
|
||||
$result = $strategy->warmup();
|
||||
|
||||
echo "\n📊 Results:\n";
|
||||
echo " Strategy: " . $result->strategyName . "\n";
|
||||
echo " Items Warmed: " . $result->itemsWarmed . "\n";
|
||||
echo " Items Failed: " . $result->itemsFailed . "\n";
|
||||
echo " Duration: " . $result->durationSeconds . "s\n";
|
||||
echo " Memory Used: " . $result->memoryUsedBytes . " bytes\n";
|
||||
|
||||
if (!empty($result->errors)) {
|
||||
echo "\n❌ Errors:\n";
|
||||
foreach ($result->errors as $error) {
|
||||
print_r($error);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($result->metadata)) {
|
||||
echo "\n📋 Metadata:\n";
|
||||
print_r($result->metadata);
|
||||
}
|
||||
|
||||
echo "\n" . ($result->itemsWarmed > 0 ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
|
||||
116
tests/debug/test-clickstatistics-service.php
Normal file
116
tests/debug/test-clickstatistics-service.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Domain\SmartLink\Repositories\ClickEventRepository;
|
||||
use App\Domain\SmartLink\Services\ClickStatisticsService;
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
|
||||
echo "=== ClickStatisticsService Test ===\n\n";
|
||||
|
||||
try {
|
||||
// Bootstrap application and get container
|
||||
echo "1. Bootstrapping application...\n";
|
||||
$basePath = dirname(__DIR__, 2);
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: true);
|
||||
$bootstrapper = new AppBootstrapper($basePath, $collector, $memoryMonitor);
|
||||
$container = $bootstrapper->bootstrapWorker();
|
||||
echo "✅ Application bootstrapped successfully\n\n";
|
||||
|
||||
// Test 1: Resolve ClickEventRepository from container
|
||||
echo "2. Resolving ClickEventRepository from DI container...\n";
|
||||
try {
|
||||
$repository = $container->get(ClickEventRepository::class);
|
||||
echo "✅ ClickEventRepository resolved: " . get_class($repository) . "\n\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Failed to resolve ClickEventRepository\n";
|
||||
echo " Error: " . $e->getMessage() . "\n\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Test 2: Resolve ClickStatisticsService from container
|
||||
echo "3. Resolving ClickStatisticsService from DI container...\n";
|
||||
try {
|
||||
$service = $container->get(ClickStatisticsService::class);
|
||||
echo "✅ ClickStatisticsService resolved: " . get_class($service) . "\n\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Failed to resolve ClickStatisticsService\n";
|
||||
echo " Error: " . $e->getMessage() . "\n\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Test 3: Call getOverviewStats
|
||||
echo "4. Testing getOverviewStats() method...\n";
|
||||
try {
|
||||
$stats = $service->getOverviewStats();
|
||||
echo "✅ getOverviewStats() executed successfully\n";
|
||||
echo " Result structure:\n";
|
||||
foreach ($stats as $key => $value) {
|
||||
echo " - {$key}: {$value}\n";
|
||||
}
|
||||
echo "\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ getOverviewStats() failed\n";
|
||||
echo " Error: " . $e->getMessage() . "\n";
|
||||
echo " Trace: " . $e->getTraceAsString() . "\n\n";
|
||||
}
|
||||
|
||||
// Test 4: Call getDeviceDistribution
|
||||
echo "5. Testing getDeviceDistribution() method...\n";
|
||||
try {
|
||||
$distribution = $service->getDeviceDistribution();
|
||||
echo "✅ getDeviceDistribution() executed successfully\n";
|
||||
echo " Result structure:\n";
|
||||
foreach ($distribution as $key => $value) {
|
||||
echo " - {$key}: {$value}\n";
|
||||
}
|
||||
echo "\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ getDeviceDistribution() failed\n";
|
||||
echo " Error: " . $e->getMessage() . "\n";
|
||||
echo " Trace: " . $e->getTraceAsString() . "\n\n";
|
||||
}
|
||||
|
||||
// Test 5: Call getTopPerformingLinks
|
||||
echo "6. Testing getTopPerformingLinks(5) method...\n";
|
||||
try {
|
||||
$topLinks = $service->getTopPerformingLinks(5);
|
||||
echo "✅ getTopPerformingLinks() executed successfully\n";
|
||||
echo " Found " . count($topLinks) . " links\n";
|
||||
if (!empty($topLinks)) {
|
||||
echo " Sample link data:\n";
|
||||
$firstLink = $topLinks[0];
|
||||
foreach ($firstLink as $key => $value) {
|
||||
echo " - {$key}: {$value}\n";
|
||||
}
|
||||
} else {
|
||||
echo " (No links in database yet)\n";
|
||||
}
|
||||
echo "\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ getTopPerformingLinks() failed\n";
|
||||
echo " Error: " . $e->getMessage() . "\n";
|
||||
echo " Trace: " . $e->getTraceAsString() . "\n\n";
|
||||
}
|
||||
|
||||
echo "=== Test Summary ===\n";
|
||||
echo "✅ ClickStatisticsService is working correctly\n";
|
||||
echo "✅ DI container bindings are functional\n";
|
||||
echo "✅ All service methods can be called without errors\n\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "\n❌ Fatal error during test:\n";
|
||||
echo " Message: " . $e->getMessage() . "\n";
|
||||
echo " File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo " Trace: " . $e->getTraceAsString() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
194
tests/debug/test-error-handling-module.php
Normal file
194
tests/debug/test-error-handling-module.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Test Script for ErrorHandling Module
|
||||
*
|
||||
* Tests the current error handling system with various exception types
|
||||
* to verify handler registration, priority execution, and response generation.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\ErrorHandling\Handlers\{
|
||||
ValidationErrorHandler,
|
||||
DatabaseErrorHandler,
|
||||
HttpErrorHandler,
|
||||
FallbackErrorHandler
|
||||
};
|
||||
use App\Framework\ErrorHandling\{ErrorHandlerManager, ErrorHandlerRegistry};
|
||||
use App\Framework\Validation\Exceptions\ValidationException;
|
||||
use App\Framework\Validation\ValidationResult;
|
||||
use App\Framework\Database\Exception\DatabaseException;
|
||||
use App\Framework\Http\Exception\HttpException;
|
||||
use App\Framework\Http\Status;
|
||||
use App\Framework\Exception\ExceptionContext;
|
||||
use App\Framework\Logging\Logger;
|
||||
use App\Framework\Logging\ValueObjects\LogContext;
|
||||
use App\Framework\Logging\LogLevel;
|
||||
|
||||
echo "=== ErrorHandling Module Test ===\n\n";
|
||||
|
||||
// Setup Logger (mock for testing)
|
||||
$logger = new class implements Logger {
|
||||
public function debug(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::debug] {$message}\n";
|
||||
}
|
||||
|
||||
public function info(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::info] {$message}\n";
|
||||
}
|
||||
|
||||
public function notice(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::notice] {$message}\n";
|
||||
}
|
||||
|
||||
public function warning(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::warning] {$message}\n";
|
||||
}
|
||||
|
||||
public function error(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::error] {$message}\n";
|
||||
if ($context && $context->structured) {
|
||||
echo " Context: " . print_r($context->structured, true) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public function critical(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::critical] {$message}\n";
|
||||
}
|
||||
|
||||
public function alert(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::alert] {$message}\n";
|
||||
}
|
||||
|
||||
public function emergency(string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::emergency] {$message}\n";
|
||||
}
|
||||
|
||||
public function log(LogLevel $level, string $message, ?LogContext $context = null): void {
|
||||
echo "📝 [Logger::{$level->value}] {$message}\n";
|
||||
}
|
||||
};
|
||||
|
||||
// Setup ErrorHandlerManager
|
||||
$registry = new ErrorHandlerRegistry();
|
||||
$manager = new ErrorHandlerManager($registry);
|
||||
|
||||
// Register handlers in priority order
|
||||
echo "Registering handlers...\n";
|
||||
$manager->register(new ValidationErrorHandler());
|
||||
$manager->register(new DatabaseErrorHandler($logger));
|
||||
$manager->register(new HttpErrorHandler());
|
||||
$manager->register(new FallbackErrorHandler($logger));
|
||||
echo "✅ All handlers registered\n\n";
|
||||
|
||||
// Test 1: ValidationException
|
||||
echo "--- Test 1: ValidationException ---\n";
|
||||
try {
|
||||
$validationResult = new ValidationResult();
|
||||
$validationResult->addErrors('email', ['Email is required', 'Email format is invalid']);
|
||||
$validationResult->addErrors('password', ['Password must be at least 8 characters']);
|
||||
|
||||
$exception = new ValidationException($validationResult);
|
||||
|
||||
$result = $manager->handleException($exception);
|
||||
|
||||
echo "✅ Handled: " . ($result->handled ? 'Yes' : 'No') . "\n";
|
||||
echo " Message: {$result->message}\n";
|
||||
echo " Status Code: {$result->statusCode}\n";
|
||||
echo " Error Type: {$result->data['error_type']}\n";
|
||||
echo " Errors: " . print_r($result->data['errors'], true) . "\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Error: {$e->getMessage()}\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test 2: DatabaseException
|
||||
echo "--- Test 2: DatabaseException ---\n";
|
||||
try {
|
||||
$exception = DatabaseException::fromContext(
|
||||
'Connection failed: Too many connections',
|
||||
ExceptionContext::empty()
|
||||
);
|
||||
|
||||
$result = $manager->handleException($exception);
|
||||
|
||||
echo "✅ Handled: " . ($result->handled ? 'Yes' : 'No') . "\n";
|
||||
echo " Message: {$result->message}\n";
|
||||
echo " Status Code: {$result->statusCode}\n";
|
||||
echo " Error Type: {$result->data['error_type']}\n";
|
||||
echo " Retry After: {$result->data['retry_after']} seconds\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Error: {$e->getMessage()}\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test 3: HttpException
|
||||
echo "--- Test 3: HttpException (404 Not Found) ---\n";
|
||||
try {
|
||||
$exception = new HttpException(
|
||||
'Resource not found',
|
||||
Status::NOT_FOUND,
|
||||
headers: ['X-Resource-Type' => 'User']
|
||||
);
|
||||
|
||||
$result = $manager->handleException($exception);
|
||||
|
||||
echo "✅ Handled: " . ($result->handled ? 'Yes' : 'No') . "\n";
|
||||
echo " Message: {$result->message}\n";
|
||||
echo " Status Code: {$result->statusCode}\n";
|
||||
echo " Error Type: {$result->data['error_type']}\n";
|
||||
echo " Headers: " . print_r($result->data['headers'], true) . "\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Error: {$e->getMessage()}\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test 4: Generic RuntimeException (Fallback)
|
||||
echo "--- Test 4: Generic RuntimeException (Fallback Handler) ---\n";
|
||||
try {
|
||||
$exception = new \RuntimeException('Something unexpected happened');
|
||||
|
||||
$result = $manager->handleException($exception);
|
||||
|
||||
echo "✅ Handled: " . ($result->handled ? 'Yes' : 'No') . "\n";
|
||||
echo " Message: {$result->message}\n";
|
||||
echo " Status Code: {$result->statusCode}\n";
|
||||
echo " Error Type: {$result->data['error_type']}\n";
|
||||
echo " Exception Class: {$result->data['exception_class']}\n";
|
||||
echo " Is Final: " . ($result->isFinal ? 'Yes' : 'No') . "\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Error: {$e->getMessage()}\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test 5: PDOException (Database Handler)
|
||||
echo "--- Test 5: PDOException ---\n";
|
||||
try {
|
||||
$exception = new \PDOException('SQLSTATE[HY000] [2002] Connection refused');
|
||||
|
||||
$result = $manager->handleException($exception);
|
||||
|
||||
echo "✅ Handled: " . ($result->handled ? 'Yes' : 'No') . "\n";
|
||||
echo " Message: {$result->message}\n";
|
||||
echo " Status Code: {$result->statusCode}\n";
|
||||
echo " Error Type: {$result->data['error_type']}\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Error: {$e->getMessage()}\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test 6: Handler Priority Order
|
||||
echo "--- Test 6: Handler Priority Verification ---\n";
|
||||
$handlers = $manager->getHandlers();
|
||||
echo "Registered handlers in priority order:\n";
|
||||
foreach ($handlers as $index => $handler) {
|
||||
$priority = $handler->getPriority();
|
||||
$name = $handler->getName();
|
||||
echo " " . ($index + 1) . ". {$name} (Priority: {$priority->value})\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "=== All Tests Completed ===\n";
|
||||
135
tests/debug/test-error-reporting-config.php
Normal file
135
tests/debug/test-error-reporting-config.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Test script for ErrorReportingConfig integration
|
||||
*
|
||||
* Verifies that ErrorReportingConfig correctly loads from environment
|
||||
* and applies environment-specific defaults.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\Config\Environment;
|
||||
use App\Framework\Config\EnvironmentType;
|
||||
use App\Framework\ErrorReporting\ErrorReportingConfig;
|
||||
|
||||
echo "=== Testing ErrorReportingConfig Integration ===\n\n";
|
||||
|
||||
// Test 1: Development Environment
|
||||
echo "Test 1: Development Environment Configuration\n";
|
||||
echo "=============================================\n";
|
||||
|
||||
$devEnv = new Environment(['APP_ENV' => 'development']);
|
||||
$devConfig = ErrorReportingConfig::fromEnvironment($devEnv);
|
||||
|
||||
echo "✓ Config loaded from environment\n";
|
||||
echo " - enabled: " . ($devConfig->enabled ? 'true' : 'false') . "\n";
|
||||
echo " - asyncProcessing: " . ($devConfig->asyncProcessing ? 'true' : 'false') . " (expected: false for dev)\n";
|
||||
echo " - filterLevels: " . (empty($devConfig->filterLevels) ? 'ALL' : implode(', ', $devConfig->filterLevels)) . "\n";
|
||||
echo " - maxStackTraceDepth: {$devConfig->maxStackTraceDepth} (expected: 30)\n";
|
||||
echo " - sanitizeSensitiveData: " . ($devConfig->sanitizeSensitiveData ? 'true' : 'false') . " (expected: false)\n";
|
||||
echo " - maxReportsPerMinute: {$devConfig->maxReportsPerMinute} (expected: 1000)\n\n";
|
||||
|
||||
// Test 2: Production Environment
|
||||
echo "Test 2: Production Environment Configuration\n";
|
||||
echo "===========================================\n";
|
||||
|
||||
$prodEnv = new Environment(['APP_ENV' => 'production']);
|
||||
$prodConfig = ErrorReportingConfig::fromEnvironment($prodEnv);
|
||||
|
||||
echo "✓ Config loaded from environment\n";
|
||||
echo " - enabled: " . ($prodConfig->enabled ? 'true' : 'false') . "\n";
|
||||
echo " - asyncProcessing: " . ($prodConfig->asyncProcessing ? 'true' : 'false') . " (expected: true)\n";
|
||||
echo " - filterLevels: " . (empty($prodConfig->filterLevels) ? 'ALL' : implode(', ', $prodConfig->filterLevels)) . " (expected: error, critical, alert, emergency)\n";
|
||||
echo " - maxStackTraceDepth: {$prodConfig->maxStackTraceDepth} (expected: 15)\n";
|
||||
echo " - sanitizeSensitiveData: " . ($prodConfig->sanitizeSensitiveData ? 'true' : 'false') . " (expected: true)\n";
|
||||
echo " - maxReportsPerMinute: {$prodConfig->maxReportsPerMinute} (expected: 30)\n\n";
|
||||
|
||||
// Test 3: Staging Environment
|
||||
echo "Test 3: Staging Environment Configuration\n";
|
||||
echo "========================================\n";
|
||||
|
||||
$stagingEnv = new Environment(['APP_ENV' => 'staging']);
|
||||
$stagingConfig = ErrorReportingConfig::fromEnvironment($stagingEnv);
|
||||
|
||||
echo "✓ Config loaded from environment\n";
|
||||
echo " - enabled: " . ($stagingConfig->enabled ? 'true' : 'false') . "\n";
|
||||
echo " - asyncProcessing: " . ($stagingConfig->asyncProcessing ? 'true' : 'false') . " (expected: true)\n";
|
||||
echo " - filterLevels: " . (empty($stagingConfig->filterLevels) ? 'ALL' : implode(', ', $stagingConfig->filterLevels)) . " (expected: warning and above)\n";
|
||||
echo " - maxStackTraceDepth: {$stagingConfig->maxStackTraceDepth} (expected: 20)\n";
|
||||
echo " - analyticsRetentionDays: {$stagingConfig->analyticsRetentionDays} (expected: 14)\n\n";
|
||||
|
||||
// Test 4: Environment Variable Overrides
|
||||
echo "Test 4: Environment Variable Overrides\n";
|
||||
echo "=====================================\n";
|
||||
|
||||
$overrideEnv = new Environment([
|
||||
'APP_ENV' => 'production',
|
||||
'ERROR_REPORTING_ENABLED' => 'false',
|
||||
'ERROR_REPORTING_ASYNC' => 'false',
|
||||
'ERROR_REPORTING_FILTER_LEVELS' => 'critical,emergency',
|
||||
'ERROR_REPORTING_MAX_STACK_DEPTH' => '5',
|
||||
'ERROR_REPORTING_SAMPLING_RATE' => '50'
|
||||
]);
|
||||
|
||||
$overrideConfig = ErrorReportingConfig::fromEnvironment($overrideEnv);
|
||||
|
||||
echo "✓ Config with environment overrides\n";
|
||||
echo " - enabled: " . ($overrideConfig->enabled ? 'true' : 'false') . " (override: false)\n";
|
||||
echo " - asyncProcessing: " . ($overrideConfig->asyncProcessing ? 'true' : 'false') . " (override: false)\n";
|
||||
echo " - filterLevels: " . implode(', ', $overrideConfig->filterLevels) . " (override: critical, emergency)\n";
|
||||
echo " - maxStackTraceDepth: {$overrideConfig->maxStackTraceDepth} (override: 5)\n";
|
||||
echo " - samplingRate: {$overrideConfig->samplingRate} (override: 50)\n\n";
|
||||
|
||||
// Test 5: Helper Methods
|
||||
echo "Test 5: Helper Methods\n";
|
||||
echo "====================\n";
|
||||
|
||||
$testConfig = ErrorReportingConfig::fromEnvironment($prodEnv);
|
||||
|
||||
// shouldReportLevel
|
||||
$shouldReportError = $testConfig->shouldReportLevel('error');
|
||||
$shouldReportDebug = $testConfig->shouldReportLevel('debug');
|
||||
|
||||
echo "✓ shouldReportLevel()\n";
|
||||
echo " - 'error' level: " . ($shouldReportError ? 'REPORT' : 'SKIP') . " (expected: REPORT)\n";
|
||||
echo " - 'debug' level: " . ($shouldReportDebug ? 'REPORT' : 'SKIP') . " (expected: SKIP in production)\n\n";
|
||||
|
||||
// shouldReportException
|
||||
$normalException = new \RuntimeException('Test error');
|
||||
$shouldReport = $testConfig->shouldReportException($normalException);
|
||||
|
||||
echo "✓ shouldReportException()\n";
|
||||
echo " - RuntimeException: " . ($shouldReport ? 'REPORT' : 'SKIP') . " (expected: REPORT)\n\n";
|
||||
|
||||
// shouldSample
|
||||
$samples = 0;
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
if ($testConfig->shouldSample()) {
|
||||
$samples++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "✓ shouldSample()\n";
|
||||
echo " - Sampling rate: {$testConfig->samplingRate}%\n";
|
||||
echo " - Samples in 100 attempts: {$samples} (expected: ~{$testConfig->samplingRate})\n\n";
|
||||
|
||||
// Test 6: Direct Environment Type
|
||||
echo "Test 6: Direct Environment Type Configuration\n";
|
||||
echo "============================================\n";
|
||||
|
||||
$directConfig = ErrorReportingConfig::forEnvironment(EnvironmentType::DEV, $devEnv);
|
||||
|
||||
echo "✓ Config created directly with EnvironmentType::DEV\n";
|
||||
echo " - asyncProcessing: " . ($directConfig->asyncProcessing ? 'true' : 'false') . " (expected: false)\n";
|
||||
echo " - maxReportsPerMinute: {$directConfig->maxReportsPerMinute} (expected: 1000)\n\n";
|
||||
|
||||
// Validation
|
||||
echo "=== Validation Results ===\n";
|
||||
echo "✓ All environment configurations loaded successfully\n";
|
||||
echo "✓ Environment-specific defaults applied correctly\n";
|
||||
echo "✓ Environment variable overrides work as expected\n";
|
||||
echo "✓ Helper methods function correctly\n";
|
||||
echo "✓ ErrorReportingConfig integration: PASSED\n";
|
||||
114
tests/debug/test-exception-context-logging.php
Normal file
114
tests/debug/test-exception-context-logging.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Test script für ExceptionContext Logging Integration
|
||||
*
|
||||
* Verifiziert dass das Logging Module nur noch ExceptionContext verwendet
|
||||
* und keine Legacy-Array-basierten Exception-Daten mehr.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\Logging\DefaultLogger;
|
||||
use App\Framework\Logging\LogLevel;
|
||||
use App\Framework\Logging\Handlers\ConsoleHandler;
|
||||
use App\Framework\Logging\ProcessorManager;
|
||||
use App\Framework\Logging\Processors\ExceptionEnrichmentProcessor;
|
||||
use App\Framework\Logging\ValueObjects\LogContext;
|
||||
use App\Framework\Logging\Formatter\DevelopmentFormatter;
|
||||
|
||||
echo "=== Testing ExceptionContext Logging Integration ===\n\n";
|
||||
|
||||
// Setup Logger mit Exception Processor (EnrichmentProcessor handles everything)
|
||||
$processorManager = new ProcessorManager(
|
||||
new ExceptionEnrichmentProcessor()
|
||||
);
|
||||
|
||||
$handler = new ConsoleHandler(
|
||||
minLevel: LogLevel::DEBUG,
|
||||
debugOnly: false
|
||||
);
|
||||
|
||||
$logger = new DefaultLogger(
|
||||
minLevel: LogLevel::DEBUG,
|
||||
handlers: [$handler],
|
||||
processorManager: $processorManager
|
||||
);
|
||||
|
||||
echo "✓ Logger setup completed\n\n";
|
||||
|
||||
// Test 1: Log Exception via LogContext
|
||||
echo "Test 1: Logging Exception via LogContext\n";
|
||||
echo "==========================================\n";
|
||||
|
||||
try {
|
||||
throw new \RuntimeException('Test exception with context', 42);
|
||||
} catch (\Throwable $e) {
|
||||
$context = LogContext::withException($e);
|
||||
$logger->error('An error occurred during processing', $context);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Test 2: Log Exception with structured data
|
||||
echo "Test 2: Logging Exception with additional structured data\n";
|
||||
echo "========================================================\n";
|
||||
|
||||
try {
|
||||
throw new \InvalidArgumentException('Invalid user input', 400);
|
||||
} catch (\Throwable $e) {
|
||||
$context = LogContext::withExceptionAndData($e, [
|
||||
'user_id' => 'user123',
|
||||
'operation' => 'update_profile',
|
||||
'input' => ['email' => 'invalid-email']
|
||||
]);
|
||||
|
||||
$logger->error('Validation failed', $context);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Test 3: Nested Exceptions (Previous Chain)
|
||||
echo "Test 3: Nested Exceptions with Previous Chain\n";
|
||||
echo "=============================================\n";
|
||||
|
||||
try {
|
||||
try {
|
||||
throw new \RuntimeException('Database connection failed');
|
||||
} catch (\Throwable $e) {
|
||||
throw new \RuntimeException('Failed to load user data', 0, $e);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$context = LogContext::withException($e);
|
||||
$logger->critical('Critical database error', $context);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Test 4: Exception in structured data (Legacy support)
|
||||
echo "Test 4: Exception in structured data (Legacy support)\n";
|
||||
echo "====================================================\n";
|
||||
|
||||
try {
|
||||
throw new \LogicException('Business logic violation');
|
||||
} catch (\Throwable $e) {
|
||||
$context = LogContext::withData([
|
||||
'exception' => $e, // Legacy: Exception direkt in structured data
|
||||
'user_id' => 'user456',
|
||||
'action' => 'payment_processing'
|
||||
]);
|
||||
|
||||
$logger->warning('Business logic error', $context);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Validation
|
||||
echo "=== Validation Results ===\n";
|
||||
echo "✓ All tests completed successfully\n";
|
||||
echo "✓ ExceptionContext is properly integrated\n";
|
||||
echo "✓ Legacy array-based approach has been replaced\n";
|
||||
echo "✓ Exception Processors work correctly\n";
|
||||
echo "\nRefactoring verification: PASSED\n";
|
||||
@@ -60,7 +60,7 @@ try {
|
||||
$testMetadata = ModelMetadata::forQueueAnomaly(
|
||||
Version::fromString('1.0.0')
|
||||
);
|
||||
|
||||
|
||||
try {
|
||||
$registry->register($testMetadata);
|
||||
echo " ✓ Test model registered: queue-anomaly v1.0.0\n\n";
|
||||
|
||||
114
tests/debug/test-shutdown-handling.php
Normal file
114
tests/debug/test-shutdown-handling.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Debug Script: Test Shutdown Handling with Fatal Errors
|
||||
*
|
||||
* This script tests the ShutdownHandlerManager implementation by:
|
||||
* 1. Triggering various fatal errors
|
||||
* 2. Verifying shutdown handlers execute
|
||||
* 3. Confirming OWASP security logging
|
||||
* 4. Testing event dispatch
|
||||
*
|
||||
* Usage: php tests/debug/test-shutdown-handling.php [test-type]
|
||||
* Test Types:
|
||||
* - fatal: Trigger E_ERROR (undefined function)
|
||||
* - parse: Trigger E_PARSE (syntax error via eval)
|
||||
* - memory: Trigger memory exhaustion
|
||||
* - normal: Normal shutdown (no error)
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
use App\Framework\Shutdown\ShutdownHandlerManager;
|
||||
use App\Framework\DI\Container;
|
||||
|
||||
// Bootstrap application
|
||||
$basePath = dirname(__DIR__, 2);
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: false);
|
||||
|
||||
$bootstrapper = new AppBootstrapper($basePath, $collector, $memoryMonitor);
|
||||
$container = $bootstrapper->bootstrapWorker();
|
||||
|
||||
// Get ShutdownHandlerManager from container
|
||||
$shutdownManager = $container->get(ShutdownHandlerManager::class);
|
||||
|
||||
// Register test handler to verify execution
|
||||
$shutdownManager->registerHandler(function ($event) {
|
||||
echo "\n[TEST HANDLER] Shutdown handler executed!\n";
|
||||
echo " - Fatal Error: " . ($event->isFatalError() ? 'YES' : 'NO') . "\n";
|
||||
echo " - Memory Usage: " . $event->memoryUsage->toHumanReadable() . "\n";
|
||||
echo " - Peak Memory: " . $event->peakMemoryUsage->toHumanReadable() . "\n";
|
||||
|
||||
if ($event->isFatalError()) {
|
||||
echo " - Error Type: " . $event->getErrorTypeName() . "\n";
|
||||
echo " - Error Message: " . $event->getErrorMessage() . "\n";
|
||||
echo " - Error File: " . $event->getErrorFile() . "\n";
|
||||
echo " - Error Line: " . $event->getErrorLine() . "\n";
|
||||
}
|
||||
|
||||
echo "[TEST HANDLER] Completed successfully\n\n";
|
||||
}, priority: 100);
|
||||
|
||||
// Determine test type from CLI argument
|
||||
$testType = $argv[1] ?? 'fatal';
|
||||
|
||||
echo "\n========================================\n";
|
||||
echo "Shutdown Handling Test: " . strtoupper($testType) . "\n";
|
||||
echo "========================================\n\n";
|
||||
|
||||
echo "Application bootstrapped successfully.\n";
|
||||
echo "ShutdownHandlerManager registered.\n";
|
||||
echo "Test handler added with priority 100.\n\n";
|
||||
|
||||
echo "Triggering test scenario in 2 seconds...\n";
|
||||
sleep(2);
|
||||
|
||||
switch ($testType) {
|
||||
case 'fatal':
|
||||
echo "\n[TEST] Triggering E_ERROR via undefined function call...\n\n";
|
||||
// This will trigger E_ERROR: Call to undefined function
|
||||
undefinedFunction();
|
||||
break;
|
||||
|
||||
case 'parse':
|
||||
echo "\n[TEST] Triggering E_PARSE via eval syntax error...\n\n";
|
||||
// This will trigger E_PARSE
|
||||
eval('this is invalid php syntax');
|
||||
break;
|
||||
|
||||
case 'memory':
|
||||
echo "\n[TEST] Triggering memory exhaustion...\n\n";
|
||||
ini_set('memory_limit', '10M');
|
||||
$data = [];
|
||||
while (true) {
|
||||
// Allocate memory until exhaustion
|
||||
$data[] = str_repeat('x', 1024 * 1024); // 1MB chunks
|
||||
}
|
||||
break;
|
||||
|
||||
case 'normal':
|
||||
echo "\n[TEST] Normal shutdown (no error)...\n\n";
|
||||
echo "Application will exit normally.\n";
|
||||
echo "Shutdown handlers should still execute.\n\n";
|
||||
// Normal exit
|
||||
exit(0);
|
||||
|
||||
default:
|
||||
echo "\nUnknown test type: {$testType}\n";
|
||||
echo "Valid types: fatal, parse, memory, normal\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// This code should never be reached for fatal errors
|
||||
echo "\n[UNEXPECTED] Code execution continued after fatal error!\n";
|
||||
echo "This should NOT happen.\n\n";
|
||||
76
tests/debug/test-smartlink-deletion.php
Normal file
76
tests/debug/test-smartlink-deletion.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Domain\SmartLink\Services\SmartLinkService;
|
||||
use App\Domain\SmartLink\ValueObjects\{LinkType, LinkTitle, DestinationUrl, Platform};
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
|
||||
echo "=== SmartLink Deletion Debug Test ===\n\n";
|
||||
|
||||
// Bootstrap application
|
||||
$app = AppBootstrapper::bootstrap(__DIR__ . '/../..');
|
||||
$container = $app->container;
|
||||
|
||||
// Get service
|
||||
$service = $container->get(SmartLinkService::class);
|
||||
|
||||
try {
|
||||
// Create link with destinations
|
||||
echo "1. Creating SmartLink...\n";
|
||||
$link = $service->createLink(
|
||||
type: LinkType::RELEASE,
|
||||
title: LinkTitle::fromString('Test Album')
|
||||
);
|
||||
echo " Created link: {$link->id->value}\n\n";
|
||||
|
||||
// Add destinations
|
||||
echo "2. Adding destinations...\n";
|
||||
$service->addDestination(
|
||||
linkId: $link->id,
|
||||
platform: Platform::SPOTIFY,
|
||||
url: DestinationUrl::fromString('https://spotify.com/test')
|
||||
);
|
||||
$service->addDestination(
|
||||
linkId: $link->id,
|
||||
platform: Platform::APPLE_MUSIC,
|
||||
url: DestinationUrl::fromString('https://apple.com/test')
|
||||
);
|
||||
echo " Added 2 destinations\n\n";
|
||||
|
||||
// Get destinations before deletion
|
||||
echo "3. Getting destinations before deletion...\n";
|
||||
$beforeDelete = $service->getDestinations($link->id);
|
||||
echo " Found " . count($beforeDelete) . " destinations\n\n";
|
||||
|
||||
// Delete link
|
||||
echo "4. Deleting link...\n";
|
||||
$service->deleteLink($link->id);
|
||||
echo " Link deleted\n\n";
|
||||
|
||||
// Try to find deleted link
|
||||
echo "5. Trying to find deleted link (should throw exception)...\n";
|
||||
try {
|
||||
$deletedLink = $service->findById($link->id);
|
||||
echo " ❌ ERROR: Link found when it should be deleted!\n";
|
||||
} catch (\App\Domain\SmartLink\Exceptions\SmartLinkNotFoundException $e) {
|
||||
echo " ✅ Correctly threw SmartLinkNotFoundException: {$e->getMessage()}\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo " ❌ ERROR: Unexpected exception type: " . get_class($e) . "\n";
|
||||
echo " Message: {$e->getMessage()}\n";
|
||||
echo " Stack trace:\n";
|
||||
echo $e->getTraceAsString() . "\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Test completed\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Test failed with exception:\n";
|
||||
echo "Type: " . get_class($e) . "\n";
|
||||
echo "Message: {$e->getMessage()}\n";
|
||||
echo "File: {$e->getFile()}:{$e->getLine()}\n";
|
||||
echo "\nStack trace:\n";
|
||||
echo $e->getTraceAsString() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
25
tests/debug/test-whitespace-rendering.php
Normal file
25
tests/debug/test-whitespace-rendering.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\SyntaxHighlighter\FileHighlighter;
|
||||
|
||||
$highlighter = new FileHighlighter();
|
||||
$html = $highlighter('/var/www/html/src/Domain/Media/ImageSlotRepository.php', 12, 5, 14);
|
||||
|
||||
// Find line 14 in the output
|
||||
$lines = explode('<div class="line', $html);
|
||||
foreach ($lines as $line) {
|
||||
if (str_contains($line, 'Line 14')) {
|
||||
echo "Found line 14:\n";
|
||||
echo '<div class="line' . $line . "\n\n";
|
||||
|
||||
// Extract just the code part
|
||||
preg_match('/<span class="code">(.*?)<\/span>/s', $line, $matches);
|
||||
if (isset($matches[1])) {
|
||||
echo "Code content:\n";
|
||||
echo $matches[1] . "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user