mirror of
https://github.com/discourse/wp-discourse.git
synced 2025-08-17 18:11:19 +08:00
* Add base log classes * Return maxFiles to normal level * Use protected class variables for folder names in folder-manager * Add unit tests for logger classes && various logger improvements * Add log viewer * Fix initialization sequence in LogViewer * Add wp-discourse settings to plugin meta * Remove metafile comments * Add partial coverage and annotate LogViewer * Add code coverage reporting and a tests readme * Tests readme xdebug section formatting * Add logging and tests to discourse-publish This abstracts remote post components to make it possible to add consistent error and log handling. Also adds basic tests coverage for discourse-publish. * Add successful publication test * Add working tests for publish_after_create and publish_after_update * Always remove test files and database upon install * Cleanup copy and assertions for existing tests * Final cleanup && verbose setting * Improve structure of publish test * Final tests, linting, security and cleanup * PHP 7.0 Compatibility * PHP 5.6 Compatibility * JSHint fixes * Update file-handler.php * Update log viewer title * Use older monolog and update file_handler function signatures * Add nonce to other view_log action * Namespace production composer packages and define build process * Update COMPOSER.md * Update FORMATTING.md * Log viewer style, naming and log-refresh improvements * Filter out all return type declarations during scoping * JsHint: Don't use default params * Update COMPOSER.md * Copy fix * Update scoper patchers notes * Address syntax issues - Remove >php7 syntax from non-required files - Add phpcs pattern exclusions to phpcs.xml - update formatting docs * discourse-publish: address all phpcs notices and add more tests Note: also added dealerdirect/phpcodesniffer-composer-installer to handle local requiring of codesniffer * Handle all phpcs warnings in lib/logs * Add todo: review phpcs exclusions to discourse-publish * Monolog cleanup - Remove unused monolog handlers, processors and formatters - Add vendor_namespaced to excluded phpcs patterns * Update CI versions to those used in composer * Switch to using composer directly in CI actions * Composer is packaged in shivammathur/setup-php * Setup PHPCS via shivammathur/setup-php * Incorrect tools key * Use vendor/bin version of phpcs * Install composer dependencies via ramsey/composer-install * Update composer.lock to composer 2 and --ignore-platform-reqs * Install lowest version of dependencies * Move dependency-versions key * Move composer-options key * Exclude vendor directory from syntax checker * Add vendor to jshintignore * Update phpcs.xml to properly exclude js css and config files * Address phpcs issues in log-viewer * Fix remaining whitespace issues created in this PR * Remove out of date sniffs and exclude specific code where necessary * Final cleanup * Properly escape html in log viewer * Remove unnecessary verbiage from documentation * Bump plugin's version to 2.2.4 Co-authored-by: Angus McLeod <angus@mcleod.org.au>
233 lines
6.7 KiB
PHP
233 lines
6.7 KiB
PHP
<?php
|
|
/**
|
|
* Class FileHandlerTest
|
|
*
|
|
* @package WPDiscourse
|
|
*/
|
|
|
|
use \WPDiscourse\Logs\Logger;
|
|
use \WPDiscourse\Logs\FileManager;
|
|
use \WPDiscourse\Logs\FileHandler;
|
|
use \WPDiscourse\Logs\LineFormatter;
|
|
|
|
/**
|
|
* FileHandler test case.
|
|
*/
|
|
class FileHandlerTest extends WP_UnitTestCase {
|
|
|
|
/**
|
|
* It creates an instance of FileHandler
|
|
*/
|
|
public function test_construct() {
|
|
$file_handler = new FileHandler( new FileManager() );
|
|
$this->assertInstanceOf( FileHandler::class, $file_handler );
|
|
}
|
|
|
|
/**
|
|
* It is enabled if the File Manager is ready
|
|
*/
|
|
public function test_enabled() {
|
|
$file_handler = new FileHandler( new FileManager() );
|
|
$this->assertTrue( $file_handler->enabled() );
|
|
}
|
|
|
|
/**
|
|
* It is not enabled if the File Manager is not ready
|
|
*/
|
|
public function test_not_enabled() {
|
|
$file_manager_double = \Mockery::mock( FileManager::class )->makePartial();
|
|
$file_manager_double->shouldReceive( 'ready' )->andReturn( false );
|
|
$file_handler = new FileHandler( $file_manager_double );
|
|
$this->assertFalse( $file_handler->enabled() );
|
|
}
|
|
|
|
/**
|
|
* It creates log files to write logs to
|
|
*/
|
|
public function test_log_file_create() {
|
|
$file_handler = new FileHandler( new FileManager() );
|
|
$logger = Logger::create( 'test', $file_handler );
|
|
$logger->info( 'New Log' );
|
|
|
|
$manager = new FileManager();
|
|
$log_files = glob( $manager->logs_dir . '/*.log' );
|
|
$this->assertCount( 1, $log_files );
|
|
|
|
$log_file = $log_files[0];
|
|
$this->assertFileExists( $log_file );
|
|
}
|
|
|
|
/**
|
|
* It writes logs to a file it has created
|
|
*/
|
|
public function test_log_file_write() {
|
|
$file_handler = new FileHandler( new FileManager() );
|
|
$logger = Logger::create( 'test', $file_handler );
|
|
$logger->info( 'New Log' );
|
|
|
|
$manager = new FileManager();
|
|
$log_files = glob( $manager->logs_dir . '/*.log' );
|
|
$this->assertCount( 1, $log_files );
|
|
|
|
$log_file = $log_files[0];
|
|
$last_entry = shell_exec( "tail -n 1 $log_file" );
|
|
$this->assertRegExp( '/New Log/', $last_entry );
|
|
}
|
|
|
|
/**
|
|
* It writes multiple logs to the same file
|
|
*/
|
|
public function test_log_file_multiple() {
|
|
$file_manager = new FileManager();
|
|
$file_handler = new FileHandler( $file_manager );
|
|
|
|
$logger = Logger::create( 'test', $file_handler );
|
|
for ( $i = 1; $i <= 10; $i++ ) {
|
|
$logger->warning( "Multi Log $i" );
|
|
}
|
|
|
|
$log_files = glob( $file_manager->logs_dir . '/*.log' );
|
|
$this->assertCount( 1, $log_files );
|
|
|
|
$matching_line_count = 0;
|
|
$handle = fopen( $log_files[0], 'r' );
|
|
while ( ! feof( $handle ) ) {
|
|
$line = fgets( $handle );
|
|
|
|
if ( strpos( $line, 'Multi Log' ) !== false ) {
|
|
$matching_line_count++;
|
|
}
|
|
}
|
|
fclose( $handle );
|
|
|
|
$this->assertEquals( 10, $matching_line_count );
|
|
}
|
|
|
|
/**
|
|
* It rotates log files every day.
|
|
*/
|
|
public function test_log_file_date_rotation() {
|
|
$file_manager = new FileManager();
|
|
$file_handler = new FileHandler( $file_manager );
|
|
|
|
$logger = Logger::create( 'test', $file_handler );
|
|
$logger->warning( "Today's Log" );
|
|
|
|
$todays_datetime = new \DateTimeImmutable( 'now' );
|
|
$tomorrows_datetime = new \DateTimeImmutable( 'tomorrow' );
|
|
|
|
// Make file handler think it's tomorrow.
|
|
$tomorrows_file_handler = new FileHandler( $file_manager, null, null, $tomorrows_datetime );
|
|
|
|
// Make logger think it's tomorrow.
|
|
$tomorrows_logger = Logger::create( 'test', $tomorrows_file_handler );
|
|
$tomorrows_logger->pushProcessor(
|
|
function ( $record ) use ( $tomorrows_datetime ) {
|
|
$record['datetime'] = $tomorrows_datetime;
|
|
return $record;
|
|
}
|
|
);
|
|
|
|
$tomorrows_logger->warning( "Tomorrow's Log" );
|
|
|
|
$tomorrows_date = $tomorrows_datetime->format( FileHandler::DATE_FORMAT );
|
|
$todays_date = $todays_datetime->format( FileHandler::DATE_FORMAT );
|
|
|
|
$files = $file_handler->list_files();
|
|
$this->assertRegExp( '/' . $tomorrows_date . '/', $files[0] );
|
|
$this->assertRegExp( '/' . $todays_date . '/', $files[1] );
|
|
}
|
|
|
|
/**
|
|
* It rotates logs when size limit is reached.
|
|
*/
|
|
public function test_log_file_size_limit_rotation() {
|
|
$file_manager = new FileManager();
|
|
$file_handler = new FileHandler( $file_manager );
|
|
|
|
$logger = Logger::create( 'high-volume', $file_handler );
|
|
$logger->warning( 'High volume log' );
|
|
|
|
// It's inefficient to create a large file via individual logs, so we're
|
|
// stuffing the log file with filler data so it's almost up to the limit
|
|
// then taking it over the limit with normal logs.
|
|
|
|
$handle = fopen( $file_handler->getUrl(), 'wb' );
|
|
$limit = $file_handler->get_file_size_limit();
|
|
|
|
while ( fstat( $handle )['size'] < ( $limit - ( 1024 * 30 * 1 ) ) ) {
|
|
fwrite( $handle, str_repeat( "filler line taking up 30 bts\n", 1024 ) );
|
|
}
|
|
|
|
for ( $i = 1; $i <= 300; $i++ ) {
|
|
$logger->warning( 'High volume log' );
|
|
}
|
|
|
|
$this->assertLessThanOrEqual( $limit, fstat( $handle )['size'] );
|
|
$this->assertCount( 2, $file_handler->list_files() );
|
|
}
|
|
|
|
/**
|
|
* It increments file numbers on each rotation.
|
|
*/
|
|
public function test_log_file_number() {
|
|
$file_manager = new FileManager();
|
|
|
|
// Size limit to restrict each file to a single line.
|
|
$low_limit_file_handler = new FileHandler( $file_manager, 200 );
|
|
|
|
$logger = Logger::create( 'one-log-per-file', $low_limit_file_handler );
|
|
|
|
for ( $i = 1; $i <= 7; $i++ ) {
|
|
$logger->warning( 'A line long enough to take it over 100 bytes with log metadata' );
|
|
}
|
|
|
|
$this->assertCount( 7, $low_limit_file_handler->list_files() );
|
|
$this->assertEquals( 7, $low_limit_file_handler->current_file_number() );
|
|
}
|
|
|
|
/**
|
|
* It respects the max_files limit.
|
|
*/
|
|
public function test_log_max_files() {
|
|
$file_manager = new FileManager();
|
|
|
|
// Size limit to restrict each file to a single line.
|
|
$handler = new FileHandler( $file_manager, 200 );
|
|
$logger = Logger::create( 'one-log-per-file', $handler );
|
|
|
|
for ( $i = 1; $i <= 15; $i++ ) {
|
|
$logger->warning( 'A line long enough to take it over 100 bytes with log metadata' );
|
|
}
|
|
|
|
$files = $handler->list_files();
|
|
|
|
$this->assertCount( 10, $files );
|
|
|
|
// Ensure the right files have been removed.
|
|
$this->assertEquals( 15, $handler->get_number_from_url( $files[0] ) );
|
|
$this->assertEquals( 6, $handler->get_number_from_url( end( $files ) ) );
|
|
}
|
|
|
|
/**
|
|
* Teardown class.
|
|
*/
|
|
public function tearDown() {
|
|
$this->clear_logs();
|
|
\Mockery::close();
|
|
}
|
|
|
|
/**
|
|
* Clear logs.
|
|
*/
|
|
private function clear_logs() {
|
|
$manager = new FileManager();
|
|
$log_files = glob( $manager->logs_dir . '/*.log' );
|
|
|
|
foreach ( $log_files as $file ) {
|
|
if ( is_file( $file ) ) {
|
|
unlink( $file );
|
|
}
|
|
}
|
|
}
|
|
}
|