= 0) { $actualStr = _dump_with_type($value); throw new AssertionFailureException($message ?: "Expected negative integer, got {$actualStr}"); } } function assert_count(int $expectedCount, $haystack, string $message = ''): void { if (!is_array($haystack) && !$haystack instanceof \Countable) { $actualStr = _dump_with_type($haystack); throw new AssertionFailureException($message ?: "Expected array or Countable, got {$actualStr}"); } $actualCount = count($haystack); if ($actualCount !== $expectedCount) { throw new AssertionFailureException($message ?: "Expected count {$expectedCount}, got {$actualCount}"); } } function assert_array_has_key($key, $array, string $message = ''): void { if (!is_array($array) && !($array instanceof \ArrayAccess)) { $actualStr = _dump_with_type($array); throw new AssertionFailureException($message ?: "Expected array or ArrayAccess, got {$actualStr}"); } if (is_array($array)) { if (!array_key_exists($key, $array)) { $keyStr = _dump($key); throw new AssertionFailureException($message ?: "Expected array to have key {$keyStr}"); } } else { if (!$array->offsetExists($key)) { $keyStr = _dump($key); throw new AssertionFailureException($message ?: "Expected ArrayAccess to have key {$keyStr}"); } } } function fail(string $message = ''): void { throw new AssertionFailureException($message ?: "Test failed"); } function assert_execution_time_less_than(float $maxMs, callable $callback, string $message = ''): void { $start = microtime(true); $callback(); $end = microtime(true); $executionTimeMs = ($end - $start) * 1000; if ($executionTimeMs > $maxMs) { throw new AssertionFailureException($message ?: "Expected execution time to be less than {$maxMs}ms, but it took {$executionTimeMs}ms"); } } function assert_memory_usage_less_than(int $maxBytes, callable $callback, string $message = ''): void { $startMemory = memory_get_usage(); $callback(); $endMemory = memory_get_usage(); $memoryUsage = $endMemory - $startMemory; if ($memoryUsage > $maxBytes) { throw new AssertionFailureException($message ?: "Expected memory usage to be less than {$maxBytes} bytes, but it used {$memoryUsage} bytes"); } } function assert_file_exists(string $path, string $message = ''): void { if (!file_exists($path)) { throw new AssertionFailureException($message ?: "Expected file '{$path}' to exist"); } } function assert_file_not_exists(string $path, string $message = ''): void { if (file_exists($path)) { throw new AssertionFailureException($message ?: "Expected file '{$path}' to not exist"); } } function assert_directory_exists(string $path, string $message = ''): void { if (!is_dir($path)) { throw new AssertionFailureException($message ?: "Expected directory '{$path}' to exist"); } } function assert_is_readable(string $path, string $message = ''): void { if (!is_readable($path)) { throw new AssertionFailureException($message ?: "Expected path '{$path}' to be readable"); } } function assert_is_writable(string $path, string $message = ''): void { if (!is_writable($path)) { throw new AssertionFailureException($message ?: "Expected path '{$path}' to be writable"); } }