Merge remote-tracking branch 'origin/develop' into develop.randompenguin1

This commit is contained in:
Philipp 2025-05-29 19:11:42 +02:00
commit 7ca99aa194
No known key found for this signature in database
GPG key ID: 24A7501396EB5432
204 changed files with 5699 additions and 2767 deletions

View file

@ -11,6 +11,7 @@ use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Addon\AddonHelper;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hook;
use Friendica\Core\Hooks\HookEventBridge;
use Friendica\DI;
use Friendica\Module\Special\HTTPException;
use Friendica\Security\Authentication;
@ -159,6 +160,13 @@ abstract class ApiTestCase extends FixtureTestCase
;
DI::init($this->dice);
/** @var \Friendica\Event\EventDispatcher */
$eventDispatcher = DI::eventDispatcher();
foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) {
$eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]);
}
$this->httpExceptionMock = $this->dice->create(HTTPException::class);
AuthTestConfig::$authenticated = true;

View file

@ -0,0 +1,26 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
namespace Friendica\Test;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Lock\Capability\ICanLock;
abstract class CacheLockTestCase extends LockTestCase
{
abstract protected function getCache(): ICanCacheInMemory;
abstract protected function getInstance(): ICanLock;
/**
* Test if the getStats() result is identically to the getCacheStats()
*/
public function testGetStats()
{
self::assertSame(array_keys($this->getCache()->getStats()), array_keys($this->instance->getCacheStats()));
}
}

View file

@ -8,21 +8,17 @@
namespace Friendica\Test;
use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Test\MockedTestCase;
abstract class LockTestCase extends MockedTestCase
{
/**
* @var int Start time of the mock (used for time operations)
* Start time of the mock (used for time operations)
*/
protected $startTime = 1417011228;
protected int $startTime = 1417011228;
protected ICanLock $instance;
/**
* @var ICanLock
*/
protected $instance;
abstract protected function getInstance(): ICanLock;
abstract protected function getInstance();
protected function setUp(): void
{
@ -205,4 +201,6 @@ abstract class LockTestCase extends MockedTestCase
self::assertFalse($this->instance->isLocked('wrongLock'));
self::assertFalse($this->instance->release('wrongLock'));
}
}

View file

@ -32,15 +32,45 @@ class HookEventBridgeTest extends TestCase
ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent',
ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent',
ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent',
ArrayFilterEvent::POST_LOCAL_START => 'onArrayFilterEvent',
ArrayFilterEvent::POST_LOCAL => 'onArrayFilterEvent',
ArrayFilterEvent::POST_LOCAL_END => 'onArrayFilterEvent',
ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT => 'onPermissionTooltipContentEvent',
ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent',
ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent',
ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onInsertPostLocalEndEvent',
ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent',
ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent',
ArrayFilterEvent::PREPARE_POST_START => 'onPreparePostStartEvent',
ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT => 'onArrayFilterEvent',
ArrayFilterEvent::PREPARE_POST => 'onArrayFilterEvent',
ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent',
ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent',
ArrayFilterEvent::PHOTO_UPLOAD_START => 'onPhotoUploadStartEvent',
ArrayFilterEvent::PHOTO_UPLOAD => 'onArrayFilterEvent',
ArrayFilterEvent::PHOTO_UPLOAD_END => 'onPhotoUploadEndEvent',
ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent',
ArrayFilterEvent::NETWORK_CONTENT_START => 'onArrayFilterEvent',
ArrayFilterEvent::NETWORK_CONTENT_TABS => 'onArrayFilterEvent',
ArrayFilterEvent::PARSE_LINK => 'onArrayFilterEvent',
ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent',
ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent',
ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent',
ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent',
ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent',
ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'onArrayFilterEvent',
ArrayFilterEvent::ENOTIFY => 'onArrayFilterEvent',
ArrayFilterEvent::ENOTIFY_STORE => 'onArrayFilterEvent',
ArrayFilterEvent::ENOTIFY_MAIL => 'onArrayFilterEvent',
ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent',
ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent',
ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent',
ArrayFilterEvent::DIRECTORY_ITEM => 'onArrayFilterEvent',
ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent',
ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent',
ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent',
ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent',
ArrayFilterEvent::PROFILE_SETTINGS_FORM => 'onArrayFilterEvent',
ArrayFilterEvent::PROFILE_SETTINGS_POST => 'onArrayFilterEvent',
ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent',
ArrayFilterEvent::ACL_LOOKUP_END => 'onArrayFilterEvent',
ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent',
ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent',
ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent',
@ -51,11 +81,34 @@ class HookEventBridgeTest extends TestCase
ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'onArrayFilterEvent',
ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'onArrayFilterEvent',
ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'onArrayFilterEvent',
ArrayFilterEvent::FOLLOW_CONTACT => 'onArrayFilterEvent',
ArrayFilterEvent::UNFOLLOW_CONTACT => 'onArrayFilterEvent',
ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent',
ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent',
ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent',
ArrayFilterEvent::EDIT_CONTACT_FORM => 'onArrayFilterEvent',
ArrayFilterEvent::EDIT_CONTACT_POST => 'onArrayFilterEvent',
ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent',
ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent',
ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'onArrayFilterEvent',
ArrayFilterEvent::ACCOUNT_REGISTER_POST => 'onArrayFilterEvent',
ArrayFilterEvent::ACCOUNT_REGISTER => 'onAccountRegisterEvent',
ArrayFilterEvent::ACCOUNT_REMOVE => 'onAccountRemoveEvent',
ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent',
ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent',
ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent',
ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent',
ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent',
ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'onArrayFilterEvent',
ArrayFilterEvent::DB_VIEW_DEFINITION => 'onArrayFilterEvent',
HtmlFilterEvent::HEAD => 'onHtmlFilterEvent',
HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent',
HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent',
HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent',
HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent',
HtmlFilterEvent::MOD_HOME_CONTENT => 'onHtmlFilterEvent',
HtmlFilterEvent::MOD_ABOUT_CONTENT => 'onHtmlFilterEvent',
HtmlFilterEvent::MOD_PROFILE_CONTENT => 'onHtmlFilterEvent',
HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent',
HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent',
];
@ -167,6 +220,155 @@ class HookEventBridgeTest extends TestCase
HookEventBridge::onCollectRoutesEvent($event);
}
public function testOnPermissionTooltipContentEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT, ['model' => ['uid' => -1]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('lockview_content', $name);
$this->assertSame(['uid' => -1], $data);
return ['uid' => 123];
});
HookEventBridge::onPermissionTooltipContentEvent($event);
$this->assertSame(
['model' => ['uid' => 123]],
$event->getArray(),
);
}
public function testOnInsertPostLocalEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, ['item' => ['id' => -1]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('post_local', $name);
$this->assertSame(['id' => -1], $data);
return ['id' => 123];
});
HookEventBridge::onInsertPostLocalEvent($event);
$this->assertSame(
['item' => ['id' => 123]],
$event->getArray(),
);
}
public function testOnInsertPostLocalEndEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, ['item' => ['id' => -1]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('post_local_end', $name);
$this->assertSame(['id' => -1], $data);
return ['id' => 123];
});
HookEventBridge::onInsertPostLocalEndEvent($event);
$this->assertSame(
['item' => ['id' => 123]],
$event->getArray(),
);
}
public function testOnPreparePostStartEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST_START, ['item' => ['id' => -1]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('prepare_body_init', $name);
$this->assertSame(['id' => -1], $data);
return ['id' => 123];
});
HookEventBridge::onPreparePostStartEvent($event);
$this->assertSame(
['item' => ['id' => 123]],
$event->getArray(),
);
}
public function testOnPhotoUploadStartEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_START, ['request' => ['album' => -1]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('photo_post_init', $name);
$this->assertSame(['album' => -1], $data);
return ['album' => 123];
});
HookEventBridge::onPhotoUploadStartEvent($event);
$this->assertSame(
['request' => ['album' => 123]],
$event->getArray(),
);
}
public function testOnPhotoUploadEndEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => -1]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, int $data): int {
$this->assertSame('photo_post_end', $name);
$this->assertSame(-1, $data);
return 123;
});
HookEventBridge::onPhotoUploadEndEvent($event);
}
public function testOnProfileSidebarEntryEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, ['profile' => ['uid' => 0, 'name' => 'original']]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('profile_sidebar_enter', $name);
$this->assertSame(['uid' => 0, 'name' => 'original'], $data);
return ['uid' => 0, 'name' => 'changed'];
});
HookEventBridge::onProfileSidebarEntryEvent($event);
$this->assertSame(
['profile' => ['uid' => 0, 'name' => 'changed']],
$event->getArray(),
);
}
public function testOnOembedFetchEndEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::OEMBED_FETCH_END, ['url' => 'original_url']);
@ -255,6 +457,74 @@ class HookEventBridgeTest extends TestCase
);
}
public function testOnEventCreatedEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_CREATED, ['event' => ['id' => 123]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, int $data): int {
$this->assertSame('event_created', $name);
$this->assertSame(123, $data);
return 123;
});
HookEventBridge::onEventCreatedEvent($event);
}
public function testOnAccountRegisterEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REGISTER, ['uid' => 123]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, int $data): int {
$this->assertSame('register_account', $name);
$this->assertSame(123, $data);
return $data;
});
HookEventBridge::onAccountRegisterEvent($event);
}
public function testOnAccountRemoveEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REMOVE, ['user' => ['uid' => 123]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, array $data): array {
$this->assertSame('remove_user', $name);
$this->assertSame(['uid' => 123], $data);
return $data;
});
HookEventBridge::onAccountRemoveEvent($event);
}
public function testOnEventUpdatedEventCallsHookWithCorrectValue(): void
{
$event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_UPDATED, ['event' => ['id' => 123]]);
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue(null, function (string $name, int $data): int {
$this->assertSame('event_updated', $name);
$this->assertSame(123, $data);
return 123;
});
HookEventBridge::onEventUpdatedEvent($event);
}
public static function getArrayFilterEventData(): array
{
return [
@ -263,21 +533,64 @@ class HookEventBridgeTest extends TestCase
[ArrayFilterEvent::NAV_INFO, 'nav_info'],
[ArrayFilterEvent::FEATURE_ENABLED, 'isEnabled'],
[ArrayFilterEvent::FEATURE_GET, 'get'],
[ArrayFilterEvent::POST_LOCAL_START, 'post_local_start'],
[ArrayFilterEvent::POST_LOCAL, 'post_local'],
[ArrayFilterEvent::POST_LOCAL_END, 'post_local_end'],
[ArrayFilterEvent::INSERT_POST_LOCAL_START, 'post_local_start'],
[ArrayFilterEvent::INSERT_POST_REMOTE, 'post_remote'],
[ArrayFilterEvent::INSERT_POST_REMOTE_END, 'post_remote_end'],
[ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT, 'prepare_body_content_filter'],
[ArrayFilterEvent::PREPARE_POST, 'prepare_body'],
[ArrayFilterEvent::PREPARE_POST_END, 'prepare_body_final'],
[ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'],
[ArrayFilterEvent::PHOTO_UPLOAD, 'photo_post_file'],
[ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'],
[ArrayFilterEvent::NETWORK_CONTENT_START, 'network_content_init'],
[ArrayFilterEvent::NETWORK_CONTENT_TABS, 'network_tabs'],
[ArrayFilterEvent::PARSE_LINK, 'parse_link'],
[ArrayFilterEvent::CONVERSATION_START, 'conversation_start'],
[ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'item_by_link'],
[ArrayFilterEvent::ITEM_TAGGED, 'tagged'],
[ArrayFilterEvent::DISPLAY_ITEM, 'display_item'],
[ArrayFilterEvent::CACHE_ITEM, 'put_item_in_cache'],
[ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, 'check_item_notification'],
[ArrayFilterEvent::ENOTIFY, 'enotify'],
[ArrayFilterEvent::ENOTIFY_STORE, 'enotify_store'],
[ArrayFilterEvent::ENOTIFY_MAIL, 'enotify_mail'],
[ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'],
[ArrayFilterEvent::RENDER_LOCATION, 'render_location'],
[ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'],
[ArrayFilterEvent::DIRECTORY_ITEM, 'directory_item'],
[ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'],
[ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'],
[ArrayFilterEvent::PROFILE_TABS, 'profile_tabs'],
[ArrayFilterEvent::PROFILE_SETTINGS_FORM, 'profile_edit'],
[ArrayFilterEvent::PROFILE_SETTINGS_POST, 'profile_post'],
[ArrayFilterEvent::MODERATION_USERS_TABS, 'moderation_users_tabs'],
[ArrayFilterEvent::ACL_LOOKUP_END, 'acl_lookup_end'],
[ArrayFilterEvent::PAGE_INFO, 'page_info_data'],
[ArrayFilterEvent::SMILEY_LIST, 'smilie'],
[ArrayFilterEvent::JOT_NETWORKS, 'jot_networks'],
[ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, 'support_follow'],
[ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW, 'support_revoke_follow'],
[ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE, 'support_probe'],
[ArrayFilterEvent::FOLLOW_CONTACT, 'follow'],
[ArrayFilterEvent::UNFOLLOW_CONTACT, 'unfollow'],
[ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'revoke_follow'],
[ArrayFilterEvent::BLOCK_CONTACT, 'block'],
[ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'],
[ArrayFilterEvent::EDIT_CONTACT_FORM, 'contact_edit'],
[ArrayFilterEvent::EDIT_CONTACT_POST, 'contact_edit_post'],
[ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'],
[ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'authenticate'],
[ArrayFilterEvent::ACCOUNT_REGISTER_FORM, 'register_form'],
[ArrayFilterEvent::ACCOUNT_REGISTER_POST, 'register_post'],
[ArrayFilterEvent::ACCOUNT_REGISTER, 'register_account'],
[ArrayFilterEvent::ACCOUNT_REMOVE, 'remove_user'],
[ArrayFilterEvent::EVENT_CREATED, 'event_created'],
[ArrayFilterEvent::EVENT_UPDATED, 'event_updated'],
[ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'],
[ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'],
[ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'],
[ArrayFilterEvent::DB_STRUCTURE_DEFINITION, 'dbstructure_definition'],
[ArrayFilterEvent::DB_VIEW_DEFINITION, 'dbview_definition'],
];
}
@ -310,6 +623,9 @@ class HookEventBridgeTest extends TestCase
[HtmlFilterEvent::PAGE_HEADER, 'page_header'],
[HtmlFilterEvent::PAGE_CONTENT_TOP, 'page_content_top'],
[HtmlFilterEvent::PAGE_END, 'page_end'],
[HtmlFilterEvent::MOD_HOME_CONTENT, 'home_content'],
[HtmlFilterEvent::MOD_ABOUT_CONTENT, 'about_hook'],
[HtmlFilterEvent::MOD_PROFILE_CONTENT, 'profile_advanced'],
[HtmlFilterEvent::JOT_TOOL, 'jot_tool'],
[HtmlFilterEvent::CONTACT_BLOCK_END, 'contact_block_end'],
];

View file

@ -0,0 +1,75 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Test\Unit\Core\Logger\Factory;
use Exception;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Factory\DelegatingLoggerFactory;
use Friendica\Core\Logger\Factory\LoggerFactory;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
class DelegatingLoggerFactoryTest extends TestCase
{
public function testCreateLoggerReturnsPsrLogger(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'logger_config', null, 'test'],
]);
$factory = new DelegatingLoggerFactory($config);
$factory->registerFactory('test', $this->createStub(LoggerFactory::class));
$this->assertInstanceOf(
LoggerInterface::class,
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT)
);
}
public function testCreateLoggerWithoutRegisteredFactoryReturnsNullLogger(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'logger_config', null, 'not-existing-factory'],
]);
$factory = new DelegatingLoggerFactory($config);
$this->assertInstanceOf(
NullLogger::class,
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT)
);
}
public function testCreateLoggerWithExceptionThrowingFactoryReturnsNullLogger(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'logger_config', null, 'test'],
]);
$factory = new DelegatingLoggerFactory($config);
$brokenFactory = $this->createStub(LoggerFactory::class);
$brokenFactory->method('createLogger')->willThrowException(new Exception());
$factory->registerFactory('test', $brokenFactory);
$this->assertInstanceOf(
NullLogger::class,
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT)
);
}
}

View file

@ -1,36 +0,0 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Test\Unit\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Factory\LegacyLoggerFactory;
use Friendica\Util\Profiler;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
class LegacyLoggerFactoryTest extends TestCase
{
public function testCreateLoggerReturnsPsrLogger(): void
{
$factory = new LegacyLoggerFactory(
$this->createStub(ICanCreateInstances::class),
$this->createStub(IManageConfigValues::class),
$this->createStub(Profiler::class),
);
$this->assertInstanceOf(
LoggerInterface::class,
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT)
);
}
}

View file

@ -0,0 +1,81 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Test\Unit\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Exception\LoggerArgumentException;
use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Core\Logger\Factory\StreamLoggerFactory;
use Friendica\Core\Logger\Util\FileSystemUtil;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
class StreamLoggerFactoryTest extends TestCase
{
public function testCreateLoggerReturnsPsrLogger(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'logfile', null, dirname(__DIR__, 4) . '/datasets/log/empty.friendica.log.txt'],
]);
$factory = new StreamLoggerFactory(
$config,
$this->createStub(IHaveCallIntrospections::class),
$this->createStub(FileSystemUtil::class),
);
$this->assertInstanceOf(
LoggerInterface::class,
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT)
);
}
public function testCreateLoggerWithInvalidLogfileThrowsException(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'logfile', null, dirname(__DIR__, 1) . '/not-existing-logfile.txt'],
]);
$factory = new StreamLoggerFactory(
$config,
$this->createStub(IHaveCallIntrospections::class),
$this->createStub(FileSystemUtil::class),
);
$this->expectException(LoggerArgumentException::class);
$this->expectExceptionMessage('tests/Unit/Core/Logger/not-existing-logfile.txt" is not a valid logfile.');
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT);
}
public function testCreateLoggerWithInvalidLoglevelThrowsException(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'logfile', null, dirname(__DIR__, 4) . '/datasets/log/empty.friendica.log.txt'],
]);
$factory = new StreamLoggerFactory(
$config,
$this->createStub(IHaveCallIntrospections::class),
$this->createStub(FileSystemUtil::class),
);
$this->expectException(LogLevelException::class);
$this->expectExceptionMessage('The log level "unsupported-loglevel" is not supported by "Friendica\Core\Logger\Type\StreamLogger".');
$factory->createLogger('unsupported-loglevel', LogChannel::DEFAULT);
}
}

View file

@ -0,0 +1,61 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Test\Unit\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Core\Logger\Factory\SyslogLoggerFactory;
use Friendica\Core\Logger\Type\SyslogLogger;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
class SyslogLoggerFactoryTest extends TestCase
{
public function testCreateLoggerReturnsPsrLogger(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'syslog_flags', null, SyslogLogger::DEFAULT_FLAGS],
['system', 'syslog_facility', null, SyslogLogger::DEFAULT_FACILITY],
]);
$factory = new SyslogLoggerFactory(
$config,
$this->createStub(IHaveCallIntrospections::class),
);
$this->assertInstanceOf(
LoggerInterface::class,
$factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT)
);
}
public function testCreateLoggerWithInvalidLoglevelThrowsException(): void
{
$config = $this->createStub(IManageConfigValues::class);
$config->method('get')->willReturnMap([
['system', 'syslog_flags', null, SyslogLogger::DEFAULT_FLAGS],
['system', 'syslog_facility', null, SyslogLogger::DEFAULT_FACILITY],
]);
$factory = new SyslogLoggerFactory(
$config,
$this->createStub(IHaveCallIntrospections::class),
);
$this->expectException(LogLevelException::class);
$this->expectExceptionMessage('The log level "unsupported-loglevel" is not supported by "Friendica\Core\Logger\Type\SyslogLogger".');
$factory->createLogger('unsupported-loglevel', LogChannel::DEFAULT);
}
}

View file

@ -29,24 +29,75 @@ class ArrayFilterEventTest extends TestCase
[ArrayFilterEvent::NAV_INFO, 'friendica.data.nav_info'],
[ArrayFilterEvent::FEATURE_ENABLED, 'friendica.data.feature_enabled'],
[ArrayFilterEvent::FEATURE_GET, 'friendica.data.feature_get'],
[ArrayFilterEvent::POST_LOCAL_START, 'friendica.data.post_local_start'],
[ArrayFilterEvent::POST_LOCAL, 'friendica.data.post_local'],
[ArrayFilterEvent::POST_LOCAL_END, 'friendica.data.post_local_end'],
[ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT, 'friendica.data.permission_tooltip_content'],
[ArrayFilterEvent::INSERT_POST_LOCAL_START, 'friendica.data.insert_post_local_start'],
[ArrayFilterEvent::INSERT_POST_LOCAL, 'friendica.data.insert_post_local'],
[ArrayFilterEvent::INSERT_POST_LOCAL_END, 'friendica.data.insert_post_local_end'],
[ArrayFilterEvent::INSERT_POST_REMOTE, 'friendica.data.insert_post_remote'],
[ArrayFilterEvent::INSERT_POST_REMOTE_END, 'friendica.data.insert_post_remote_end'],
[ArrayFilterEvent::PREPARE_POST_START, 'friendica.data.prepare_post_start'],
[ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT, 'friendica.data.prepare_post_filter_content'],
[ArrayFilterEvent::PREPARE_POST, 'friendica.data.prepare_post'],
[ArrayFilterEvent::PREPARE_POST_END, 'friendica.data.prepare_post_end'],
[ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'],
[ArrayFilterEvent::PHOTO_UPLOAD_START, 'friendica.data.photo_upload_start'],
[ArrayFilterEvent::PHOTO_UPLOAD, 'friendica.data.photo_upload'],
[ArrayFilterEvent::PHOTO_UPLOAD_END, 'friendica.data.photo_upload_end'],
[ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'],
[ArrayFilterEvent::NETWORK_CONTENT_START, 'friendica.data.network_content_start'],
[ArrayFilterEvent::NETWORK_CONTENT_TABS, 'friendica.data.network_content_tabs'],
[ArrayFilterEvent::PARSE_LINK, 'friendica.data.parse_link'],
[ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'],
[ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'friendica.data.fetch_item_by_link'],
[ArrayFilterEvent::ITEM_TAGGED, 'friendica.data.item_tagged'],
[ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'],
[ArrayFilterEvent::CACHE_ITEM, 'friendica.data.cache_item'],
[ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, 'friendica.data.check_item_notification'],
[ArrayFilterEvent::ENOTIFY, 'friendica.data.enotify'],
[ArrayFilterEvent::ENOTIFY_STORE, 'friendica.data.enotify_store'],
[ArrayFilterEvent::ENOTIFY_MAIL, 'friendica.data.enotify_mail'],
[ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'],
[ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'],
[ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'],
[ArrayFilterEvent::DIRECTORY_ITEM, 'friendica.data.directory_item'],
[ArrayFilterEvent::CONTACT_PHOTO_MENU, 'friendica.data.contact_photo_menu'],
[ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'friendica.data.profile_sidebar_entry'],
[ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'],
[ArrayFilterEvent::PROFILE_TABS, 'friendica.data.profile_tabs'],
[ArrayFilterEvent::PROFILE_SETTINGS_FORM, 'friendica.data.profile_settings_form'],
[ArrayFilterEvent::PROFILE_SETTINGS_POST, 'friendica.data.profile_settings_post'],
[ArrayFilterEvent::MODERATION_USERS_TABS, 'friendica.data.moderation_users_tabs'],
[ArrayFilterEvent::ACL_LOOKUP_END, 'friendica.data.acl_lookup_end'],
[ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'],
[ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'],
[ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'],
[ArrayFilterEvent::BBCODE_TO_HTML_START, 'friendica.data.bbcode_to_html_start'],
[ArrayFilterEvent::HTML_TO_BBCODE_END, 'friendica.data.html_to_bbcode_end'],
[ArrayFilterEvent::BBCODE_TO_MARKDOWN_END, 'friendica.data.bbcode_to_markdown_end'],
[ArrayFilterEvent::JOT_NETWORKS, 'friendica.data.jot_networks'],
[ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, 'friendica.data.protocol_supports_follow'],
[ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW, 'friendica.data.protocol_supports_revoke_follow'],
[ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE, 'friendica.data.protocol_supports_probe'],
[ArrayFilterEvent::FOLLOW_CONTACT, 'friendica.data.follow_contact'],
[ArrayFilterEvent::UNFOLLOW_CONTACT, 'friendica.data.unfollow_contact'],
[ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'friendica.data.revoke_follow_contact'],
[ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'],
[ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'],
[ArrayFilterEvent::EDIT_CONTACT_FORM, 'friendica.data.edit_contact_form'],
[ArrayFilterEvent::EDIT_CONTACT_POST, 'friendica.data.edit_contact_post'],
[ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'],
[ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'friendica.data.account_authenticate'],
[ArrayFilterEvent::ACCOUNT_REGISTER_FORM, 'friendica.data.account_register_form'],
[ArrayFilterEvent::ACCOUNT_REGISTER_POST, 'friendica.data.account_register_post'],
[ArrayFilterEvent::ACCOUNT_REGISTER, 'friendica.data.account_register'],
[ArrayFilterEvent::ACCOUNT_REMOVE, 'friendica.data.account_remove'],
[ArrayFilterEvent::EVENT_CREATED, 'friendica.data.event_created'],
[ArrayFilterEvent::EVENT_UPDATED, 'friendica.data.event_updated'],
[ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'],
[ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'],
[ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'],
[ArrayFilterEvent::DB_STRUCTURE_DEFINITION, 'friendica.data.db_structure_definition'],
[ArrayFilterEvent::DB_VIEW_DEFINITION, 'friendica.data.db_view_definition'],
];
}

View file

@ -27,8 +27,14 @@ class HtmlFilterEventTest extends TestCase
return [
[HtmlFilterEvent::HEAD, 'friendica.html.head'],
[HtmlFilterEvent::FOOTER, 'friendica.html.footer'],
[HtmlFilterEvent::PAGE_HEADER, 'friendica.html.page_header'],
[HtmlFilterEvent::PAGE_CONTENT_TOP, 'friendica.html.page_content_top'],
[HtmlFilterEvent::PAGE_END, 'friendica.html.page_end'],
[HtmlFilterEvent::MOD_HOME_CONTENT, 'friendica.html.mod_home_content'],
[HtmlFilterEvent::MOD_ABOUT_CONTENT, 'friendica.html.mod_about_content'],
[HtmlFilterEvent::MOD_PROFILE_CONTENT, 'friendica.html.mod_profile_content'],
[HtmlFilterEvent::JOT_TOOL, 'friendica.html.jot_tool'],
[HtmlFilterEvent::CONTACT_BLOCK_END, 'friendica.html.contact_block_end'],
];
}

View file

@ -0,0 +1,31 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types=1);
namespace Friendica\Test\Util;
use Psr\EventDispatcher\EventDispatcherInterface;
/**
* Defines a dispatcher for events.
*/
final class FakeEventDispatcher implements EventDispatcherInterface
{
/**
* Provide all relevant listeners with an event to process.
*
* @template T of object
* @param T $event
*
* @return T The passed $event MUST be returned
*/
public function dispatch(object $event): object
{
return $event;
}
}

View file

@ -13,11 +13,11 @@ use Friendica\Model\Notification;
return [
'gserver' => [
[
'url' => 'https://friendica.local',
'nurl' => 'http://friendica.local',
'register_policy' => 0,
'url' => 'https://friendica.local',
'nurl' => 'http://friendica.local',
'register_policy' => 0,
'registered-users' => 0,
'network' => 'unkn',
'network' => 'unkn',
],
],
// Base test config to avoid notice messages
@ -88,6 +88,11 @@ return [
'uri' => 'https://friendica.local/profile/mutualcontact',
'guid' => '46',
],
[
'id' => 49,
'uri' => 'https://domain.tld/profile/remotecontact',
'guid' => '49',
],
[
'id' => 100,
'uri' => 'https://friendica.local/posts/100',
@ -214,6 +219,23 @@ return [
'network' => Protocol::DFRN,
'location' => 'DFRN',
],
[
'id' => 49,
'uid' => 0,
'uri-id' => 43,
'name' => 'Remote user',
'nick' => 'remotecontact',
'self' => 0,
'nurl' => 'http://domain.tld/profile/remotecontact',
'url' => 'https://domain.tld/profile/remotecontact',
'alias' => 'https://domain.tld/~remotecontact',
'about' => 'User used in tests',
'pending' => 0,
'blocked' => 0,
'rel' => Contact::FOLLOWER,
'network' => Protocol::ACTIVITYPUB,
'location' => 'AP',
],
],
'apcontact' => [
[
@ -343,7 +365,7 @@ return [
'suscipit aut facilis ut inventore omnis exercitationem quo magnam ' .
'consequatur maxime aut illum soluta quaerat natus unde aspernatur ' .
'et sed beatae nihil ullam temporibus corporis ratione blanditiis',
'plink' => 'https://friendica.local/display/6',
'plink' => 'https://friendica.local/display/6',
],
[
'uri-id' => 100,
@ -912,8 +934,8 @@ return [
],
'profile' => [
[
'id' => 1,
'uid' => 42,
'id' => 1,
'uid' => 42,
'locality' => 'DFRN',
],
],
@ -933,18 +955,18 @@ return [
],
'group_member' => [
[
'id' => 1,
'gid' => 1,
'id' => 1,
'gid' => 1,
'contact-id' => 43,
],
[
'id' => 2,
'gid' => 1,
'id' => 2,
'gid' => 1,
'contact-id' => 43,
],
[
'id' => 3,
'gid' => 2,
'id' => 3,
'gid' => 2,
'contact-id' => 43,
],
],

View file

@ -17,7 +17,6 @@ return [
'temppath' => '/tmp/friendica.local',
'theme' => 'frio',
'url' => 'https://friendica.local',
'urlpath' => '',
'build' => 1508,
'maintenance' => false,
'dbupdate' => 1,

View file

@ -129,7 +129,6 @@ class AutomaticInstallationConsoleTest extends ConsoleTestCase
],
'system' => [
'basepath' => '',
'urlpath' => '',
'url' => 'http://friendica.local',
'ssl_policy' => 0,
'default_timezone' => '',
@ -152,7 +151,6 @@ class AutomaticInstallationConsoleTest extends ConsoleTestCase
'admin_email' => 'admin@philipp.info',
],
'system' => [
'urlpath' => 'test/it',
'url' => 'http://friendica.local/test/it',
'basepath' => '',
'ssl_policy' => '2',
@ -176,7 +174,6 @@ class AutomaticInstallationConsoleTest extends ConsoleTestCase
'admin_email' => 'admin@philipp.info',
],
'system' => [
'urlpath' => 'test/it',
'url' => 'https://friendica.local/test/it',
'basepath' => '',
'ssl_policy' => '1',
@ -352,7 +349,6 @@ FIN;
self::assertConfigEntry('system', 'default_timezone', $assertion, ($default) ? Installer::DEFAULT_TZ : null);
self::assertConfigEntry('system', 'language', $assertion, ($default) ? Installer::DEFAULT_LANG : null);
self::assertConfigEntry('system', 'url', $assertion);
self::assertConfigEntry('system', 'urlpath', $assertion);
self::assertConfigEntry('system', 'ssl_policy', $assertion, ($default) ? App\BaseURL::DEFAULT_SSL_SCHEME : null);
self::assertConfigEntry('system', 'basepath', ($realBasepath) ? $this->root->url() : $assertion);
}
@ -446,7 +442,6 @@ return [
],
'system' => [
'basepath' => '{$conf('system', 'basepath')}',
'urlpath' => '{$conf('system', 'urlpath')}',
'url' => '{$conf('system', 'url')}',
'ssl_policy' => '{$conf('system', 'ssl_policy')}',
'default_timezone' => '{$conf('system', 'default_timezone')}',
@ -604,7 +599,7 @@ CONF;
self::assertStuckDB($txt);
self::assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php'));
self::assertConfig(['config' => ['hostname' => 'friendica.local'], 'system' => ['url' => 'http://friendica.local', 'ssl_policy' => 0, 'urlpath' => '']], false, true, false, true);
self::assertConfig(['config' => ['hostname' => 'friendica.local'], 'system' => ['url' => 'http://friendica.local', 'ssl_policy' => 0]], false, true, false, true);
}
public function testGetHelp()

View file

@ -73,51 +73,51 @@ class BBCodeTest extends FixtureTestCase
],
'no-protocol' => [
'data' => 'example.com/path',
'assertHTML' => false
'assertHTML' => false,
],
'wrong-protocol' => [
'data' => 'ftp://example.com',
'assertHTML' => false
'assertHTML' => false,
],
'wrong-domain-without-path' => [
'data' => 'http://example',
'assertHTML' => false
'assertHTML' => false,
],
'wrong-domain-with-path' => [
'data' => 'http://example/path',
'assertHTML' => false
'assertHTML' => false,
],
'bug-6857-domain-start' => [
'data' => "http://\nexample.com",
'assertHTML' => false
'assertHTML' => false,
],
'bug-6857-domain-end' => [
'data' => "http://example\n.com",
'assertHTML' => false
'assertHTML' => false,
],
'bug-6857-tld' => [
'data' => "http://example.\ncom",
'assertHTML' => false
'assertHTML' => false,
],
'bug-6857-end' => [
'data' => "http://example.com\ntest",
'assertHTML' => false
'assertHTML' => false,
],
'bug-6901' => [
'data' => "http://example.com<ul>",
'assertHTML' => false
'assertHTML' => false,
],
'bug-7150' => [
'data' => html_entity_decode('http://example.com&nbsp;', ENT_QUOTES, 'UTF-8'),
'assertHTML' => false
'assertHTML' => false,
],
'bug-7271-query-string-brackets' => [
'data' => 'https://example.com/search?q=square+brackets+[url]',
'assertHTML' => true
'assertHTML' => true,
],
'bug-7271-path-brackets' => [
'data' => 'http://example.com/path/to/file[3].html',
'assertHTML' => true
'assertHTML' => true,
],
];
}
@ -215,19 +215,19 @@ class BBCodeTest extends FixtureTestCase
],
'bug-9611-purify-xss-nobb' => [
'expectedHTML' => '<span>dare to move your mouse here</span>',
'text' => '[nobb]<span onmouseover="alert(0)">dare to move your mouse here</span>[/nobb]'
'text' => '[nobb]<span onmouseover="alert(0)">dare to move your mouse here</span>[/nobb]',
],
'bug-9611-purify-xss-noparse' => [
'expectedHTML' => '<span>dare to move your mouse here</span>',
'text' => '[noparse]<span onmouseover="alert(0)">dare to move your mouse here</span>[/noparse]'
'text' => '[noparse]<span onmouseover="alert(0)">dare to move your mouse here</span>[/noparse]',
],
'bug-9611-purify-xss-attributes' => [
'expectedHTML' => '<span>dare to move your mouse here</span>',
'text' => '[color="onmouseover=alert(0) style="]dare to move your mouse here[/color]'
'text' => '[color="onmouseover=alert(0) style="]dare to move your mouse here[/color]',
],
'bug-9611-purify-attributes-correct' => [
'expectedHTML' => '<span style="color:#FFFFFF;">dare to move your mouse here</span>',
'text' => '[color=FFFFFF]dare to move your mouse here[/color]'
'text' => '[color=FFFFFF]dare to move your mouse here[/color]',
],
'bug-9639-span-classes' => [
'expectedHTML' => '<span class="arbitrary classes">Test</span>',
@ -308,11 +308,11 @@ Karl Marx - Die ursprüngliche Akkumulation
],
'bug-12701-quotes' => [
'expected' => '[![abc"fgh](https://domain.tld/photo/86912721086415cdc8e0a03226831581-1.png)](https://domain.tld/photos/user/image/86912721086415cdc8e0a03226831581)',
'text' => '[url=https://domain.tld/photos/user/image/86912721086415cdc8e0a03226831581][img=https://domain.tld/photo/86912721086415cdc8e0a03226831581-1.png]abc"fgh[/img][/url]'
'text' => '[url=https://domain.tld/photos/user/image/86912721086415cdc8e0a03226831581][img=https://domain.tld/photo/86912721086415cdc8e0a03226831581-1.png]abc"fgh[/img][/url]',
],
'bug-12701-no-quotes' => [
'expected' => '[![abcfgh](https://domain.tld/photo/86912721086415cdc8e0a03226831581-1.png "abcfgh")](https://domain.tld/photos/user/image/86912721086415cdc8e0a03226831581)',
'text' => '[url=https://domain.tld/photos/user/image/86912721086415cdc8e0a03226831581][img=https://domain.tld/photo/86912721086415cdc8e0a03226831581-1.png]abcfgh[/img][/url]'
'text' => '[url=https://domain.tld/photos/user/image/86912721086415cdc8e0a03226831581][img=https://domain.tld/photo/86912721086415cdc8e0a03226831581-1.png]abcfgh[/img][/url]',
],
/** @see https://github.com/friendica/friendica/pull/14908 */
'task-14908-strip-tags' => [
@ -350,7 +350,7 @@ Karl Marx - Die ursprüngliche Akkumulation
'bug-10692-start-line' => [
'#[url=https://friendica.local/search?tag=L160]L160[/url]',
'#L160',
]
],
];
}
@ -367,6 +367,58 @@ Karl Marx - Die ursprüngliche Akkumulation
self::assertEquals($expected, $actual);
}
public function dataExpandVideoLinks(): array
{
return [
/** @see https://github.com/friendica/friendica/pull/14940 */
'task-14940-youtube-watch-with-www' => [
'expectedBBCode' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
'text' => '[youtube]https://www.youtube.com/watch?v=hfwbmTzBFT0[/youtube]',
],
'task-14940-youtube-watch-without-www' => [
'expectedBBCode' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
'text' => '[youtube]https://youtube.com/watch?v=hfwbmTzBFT0[/youtube]',
],
'task-14940-youtube-shorts-with-www' => [
'expectedBBCode' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
'text' => '[youtube]https://www.youtube.com/shorts/hfwbmTzBFT0[/youtube]',
],
'task-14940-youtube-shorts-without-www' => [
'expectedBBCode' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
'text' => '[youtube]https://youtube.com/shorts/hfwbmTzBFT0[/youtube]',
],
'task-14940-youtube-embed-with-www' => [
'expectedBBCode' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
'text' => '[youtube]https://www.youtube.com/embed/hfwbmTzBFT0[/youtube]',
],
'task-14940-youtube-embed-without-www' => [
'expectedBBCode' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
'text' => '[youtube]https://youtube.com/embed/hfwbmTzBFT0[/youtube]',
],
'task-14940-vimeo' => [
'expectedBBCode' => '[url=https://vimeo.com/2345345]https://vimeo.com/2345345[/url]',
'text' => '[vimeo]https://vimeo.com/2345345[/vimeo]',
],
'task-14940-player-vimeo' => [
'expectedBBCode' => '[url=https://vimeo.com/2345345]https://vimeo.com/2345345[/url]',
'text' => '[vimeo]https://player.vimeo.com/video/2345345[/vimeo]',
],
];
}
/**
* @dataProvider dataExpandVideoLinks
*
* @param string $expected Expected BBCode output
* @param string $text Input text
*/
public function testExpandVideoLinks(string $expected, string $text)
{
$actual = BBCode::expandVideoLinks($text);
self::assertEquals($expected, $actual);
}
public function dataGetAbstract(): array
{
return [
@ -620,4 +672,27 @@ Lucas: For the right price, yes.[/share]',
self::assertEquals($expected, $actual);
}
public function dataProfileLink(): array
{
return [
'mention' => [
'expected' => 'Test 1: <bdi>@<a href="https://domain.tld/~remotecontact" class="userinfo mention" title="Remote contact">Remote contact</a></bdi>',
'text' => 'Test 1: @[url=https://domain.tld/profile/remotecontact]Remote contact[/url]',
],
];
}
/**
* @dataProvider dataProfileLink
*
* @param string $expected Expected BBCode output
* @param string $text Input text
*/
public function testProfileLink(string $expected, string $text)
{
$actual = BBCode::convertForUriId(0, $text);
self::assertEquals($expected, $actual);
}
}

View file

@ -51,7 +51,45 @@ class MarkdownTest extends FixtureTestCase
return [
'bug-8358-double-decode' => [
'expectedBBCode' => 'with the <sup> and </sup> tag',
'markdown' => 'with the &lt;sup&gt; and &lt;/sup&gt; tag',
'markdown' => 'with the &lt;sup&gt; and &lt;/sup&gt; tag',
],
/** @see https://github.com/friendica/friendica/pull/14940 */
'task-14940-youtube-watch-with-www' => [
'expectedBBCode' => '[youtube]hfwbmTzBFT0[/youtube]',
'markdown' => '[url=https://www.youtube.com/watch?v=hfwbmTzBFT0]https://www.youtube.com/watch?v=hfwbmTzBFT0[/url]',
],
'task-14940-youtube-watch-without-www' => [
'expectedBBCode' => '[youtube]hfwbmTzBFT0[/youtube]',
'markdown' => '[url=https://youtube.com/watch?v=hfwbmTzBFT0]https://youtube.com/watch?v=hfwbmTzBFT0[/url]',
],
'task-14940-youtube-shorts-with-www' => [
'expectedBBCode' => '[youtube]hfwbmTzBFT0[/youtube]',
'markdown' => '[url=https://www.youtube.com/shorts/hfwbmTzBFT0]https://www.youtube.com/shorts/hfwbmTzBFT0[/url]',
],
'task-14940-youtube-shorts-without-www' => [
'expectedBBCode' => '[youtube]hfwbmTzBFT0[/youtube]',
'markdown' => '[url=https://youtube.com/shorts/hfwbmTzBFT0]https://youtube.com/shorts/hfwbmTzBFT0[/url]',
],
'task-14940-youtube-embed-with-www' => [
'expectedBBCode' => '[youtube]hfwbmTzBFT0[/youtube]',
'markdown' => '[url=https://www.youtube.com/embed/hfwbmTzBFT0]https://www.youtube.com/embed/hfwbmTzBFT0[/url]',
],
'task-14940-youtube-embed-without-www' => [
'expectedBBCode' => '[youtube]hfwbmTzBFT0[/youtube]',
'markdown' => '[url=https://youtube.com/embed/hfwbmTzBFT0]https://youtube.com/embed/hfwbmTzBFT0[/url]',
],
// @todo - should we really ignore the URL content in favor of parsing the link of the body?
'task-14940-vimeo-custom-url' => [
'expectedBBCode' => '[vimeo]2345345[/vimeo]',
'markdown' => '[url=https://no.thing]https://vimeo.com/2345345[/url]',
],
'task-14940-vimeo-custom-text' => [
'expectedBBCode' => '[vimeo]2345345[/vimeo]',
'markdown' => '[url=https://vimeo.com/2345345]CustomText[/url]',
],
'task-14940-player-vimeo' => [
'expectedBBCode' => '[vimeo]2345345[/vimeo]',
'markdown' => '[url=https://player.vimeo.com/video/2345345]https://player.vimeo.com/video/2345345[/url]',
],
];
}

View file

@ -35,4 +35,18 @@ class APCuCacheTest extends MemoryCacheTestCase
$this->cache->clear(false);
parent::tearDown();
}
/**
* @small
*/
public function testStats()
{
$stats = $this->instance->getStats();
self::assertNotNull($stats['entries']);
self::assertNotNull($stats['used_memory']);
self::assertNotNull($stats['hits']);
self::assertNotNull($stats['misses']);
self::assertNotNull($stats['avail_mem']);
}
}

View file

@ -33,4 +33,12 @@ class ArrayCacheTest extends MemoryCacheTestCase
self::markTestSkipped("Array Cache doesn't support TTL");
return true;
}
/**
* @small
*/
public function testGetStats()
{
self::assertEmpty($this->cache->getStats());
}
}

View file

@ -59,4 +59,21 @@ class MemcacheCacheTest extends MemoryCacheTestCase
{
static::markTestIncomplete('Race condition because of too fast getAllKeys() which uses a workaround');
}
/**
* @small
*/
public function testStats()
{
$stats = $this->instance->getStats();
self::assertNotNull($stats['version']);
self::assertIsNumeric($stats['hits']);
self::assertIsNumeric($stats['misses']);
self::assertIsNumeric($stats['evictions']);
self::assertIsNumeric($stats['entries']);
self::assertIsNumeric($stats['used_memory']);
self::assertGreaterThan(0, $stats['connected_clients']);
self::assertGreaterThan(0, $stats['uptime']);
}
}

View file

@ -58,4 +58,21 @@ class MemcachedCacheTest extends MemoryCacheTestCase
{
static::markTestIncomplete('Race condition because of too fast getAllKeys() which uses a workaround');
}
/**
* @small
*/
public function testStats()
{
$stats = $this->instance->getStats();
self::assertNotNull($stats['version']);
self::assertIsNumeric($stats['hits']);
self::assertIsNumeric($stats['misses']);
self::assertIsNumeric($stats['evictions']);
self::assertIsNumeric($stats['entries']);
self::assertIsNumeric($stats['used_memory']);
self::assertGreaterThan(0, $stats['connected_clients']);
self::assertGreaterThan(0, $stats['uptime']);
}
}

View file

@ -0,0 +1,56 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
namespace Core\Cache;
use Friendica\Core\Cache\Type\ArrayCache;
use Friendica\Core\Cache\Type\ProfilerCacheDecorator;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Test\MemoryCacheTestCase;
use Friendica\Util\Profiler;
class ProfilerCacheDecoratorTest extends MemoryCacheTestCase
{
protected function getInstance()
{
$config = \Mockery::mock(IManageConfigValues::class);
$config->shouldReceive('get')->with('system', 'profiler')->once()->andReturn(false);
$config->shouldReceive('get')->with('rendertime', 'callstack')->once()->andReturn(false);
$this->cache = new ProfilerCacheDecorator(new ArrayCache('localhost'), new Profiler($config));
return $this->cache;
}
protected function tearDown(): void
{
$this->cache->clear(false);
parent::tearDown();
}
/**
* @doesNotPerformAssertions
*/
public function testTTL()
{
// Array Cache doesn't support TTL
self::markTestSkipped("Array Cache doesn't support TTL");
return true;
}
/**
* @small
*/
public function testGetStats()
{
self::assertEmpty($this->cache->getStats());
}
public function testGetName()
{
self::assertStringEndsWith(' (with profiler)', $this->instance->getName());
}
}

View file

@ -57,4 +57,21 @@ class RedisCacheTest extends MemoryCacheTestCase
$this->cache->clear(false);
parent::tearDown();
}
/**
* @small
*/
public function testStats()
{
$stats = $this->instance->getStats();
self::assertNotNull($stats['version']);
self::assertIsNumeric($stats['hits']);
self::assertIsNumeric($stats['misses']);
self::assertIsNumeric($stats['evictions']);
self::assertIsNumeric($stats['entries']);
self::assertIsNumeric($stats['used_memory']);
self::assertGreaterThan(0, $stats['connected_clients']);
self::assertGreaterThan(0, $stats['uptime']);
}
}

View file

@ -7,26 +7,39 @@
namespace Friendica\Test\src\Core\Lock;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\APCuCache;
use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Core\Lock\Type\CacheLock;
use Friendica\Test\LockTestCase;
use Friendica\Test\CacheLockTestCase;
/**
* @group APCU
*/
class APCuCacheLockTest extends LockTestCase
class APCuCacheLockTest extends CacheLockTestCase
{
private APCuCache $cache;
private ICanLock $lock;
protected function setUp(): void
{
if (!APCuCache::isAvailable()) {
static::markTestSkipped('APCu is not available');
}
$this->cache = new APCuCache('localhost');
$this->lock = new CacheLock($this->cache);
parent::setUp();
}
protected function getInstance()
protected function getInstance(): CacheLock
{
return new CacheLock(new APCuCache('localhost'));
return $this->lock;
}
protected function getCache(): ICanCacheInMemory
{
return $this->cache;
}
}

View file

@ -7,15 +7,32 @@
namespace Friendica\Test\src\Core\Lock;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\ArrayCache;
use Friendica\Core\Lock\Type\CacheLock;
use Friendica\Test\LockTestCase;
use Friendica\Test\CacheLockTestCase;
class ArrayCacheLockTest extends LockTestCase
class ArrayCacheLockTest extends CacheLockTestCase
{
protected function getInstance()
private CacheLock $lock;
private ArrayCache $cache;
protected function setUp(): void
{
return new CacheLock(new ArrayCache('localhost'));
$this->cache = new ArrayCache('localhost');
$this->lock = new CacheLock($this->cache);
parent::setUp();
}
protected function getInstance(): CacheLock
{
return $this->lock;
}
protected function getCache(): ICanCacheInMemory
{
return $this->cache;
}
/**

View file

@ -7,6 +7,7 @@
namespace Friendica\Test\src\Core\Lock;
use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Core\Lock\Type\DatabaseLock;
use Friendica\Test\LockTestCase;
use Friendica\Test\Util\CreateDatabaseTrait;
@ -26,7 +27,7 @@ class DatabaseLockDriverTest extends LockTestCase
parent::setUp();
}
protected function getInstance()
protected function getInstance(): ICanLock
{
return new DatabaseLock($this->getDbInstance(), $this->pid);
}

View file

@ -8,19 +8,23 @@
namespace Friendica\Test\src\Core\Lock;
use Exception;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\MemcacheCache;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Lock\Type\CacheLock;
use Friendica\Test\LockTestCase;
use Friendica\Test\CacheLockTestCase;
use Mockery;
/**
* @requires extension Memcache
* @group MEMCACHE
*/
class MemcacheCacheLockTest extends LockTestCase
class MemcacheCacheLockTest extends CacheLockTestCase
{
protected function getInstance()
private CacheLock $lock;
private MemcacheCache $cache;
protected function setUp(): void
{
$configMock = Mockery::mock(IManageConfigValues::class);
@ -36,16 +40,24 @@ class MemcacheCacheLockTest extends LockTestCase
->with('system', 'memcache_port')
->andReturn($port);
$lock = null;
try {
$cache = new MemcacheCache($host, $configMock);
$lock = new CacheLock($cache);
$this->cache = new MemcacheCache($host, $configMock);
$this->lock = new CacheLock($this->cache);
} catch (Exception $e) {
static::markTestSkipped('Memcache is not available');
}
return $lock;
parent::setUp();
}
protected function getInstance(): CacheLock
{
return $this->lock;
}
protected function getCache(): ICanCacheInMemory
{
return $this->cache;
}
/**

View file

@ -8,10 +8,11 @@
namespace Friendica\Test\src\Core\Lock;
use Exception;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\MemcachedCache;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Lock\Type\CacheLock;
use Friendica\Test\LockTestCase;
use Friendica\Test\CacheLockTestCase;
use Mockery;
use Psr\Log\NullLogger;
@ -19,9 +20,12 @@ use Psr\Log\NullLogger;
* @requires extension memcached
* @group MEMCACHED
*/
class MemcachedCacheLockTest extends LockTestCase
class MemcachedCacheLockTest extends CacheLockTestCase
{
protected function getInstance()
private MemcachedCache $cache;
private CacheLock $lock;
protected function setUp(): void
{
$configMock = Mockery::mock(IManageConfigValues::class);
@ -35,16 +39,24 @@ class MemcachedCacheLockTest extends LockTestCase
$logger = new NullLogger();
$lock = null;
try {
$cache = new MemcachedCache($host, $configMock, $logger);
$lock = new CacheLock($cache);
$this->cache = new MemcachedCache($host, $configMock, $logger);
$this->lock = new CacheLock($this->cache);
} catch (Exception $e) {
static::markTestSkipped('Memcached is not available');
}
return $lock;
parent::setUp();
}
protected function getInstance(): CacheLock
{
return $this->lock;
}
protected function getCache(): ICanCacheInMemory
{
return $this->cache;
}
/**

View file

@ -8,19 +8,20 @@
namespace Friendica\Test\src\Core\Lock;
use Exception;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\RedisCache;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Lock\Type\CacheLock;
use Friendica\Test\LockTestCase;
use Friendica\Test\CacheLockTestCase;
use Mockery;
/**
* @requires extension redis
* @group REDIS
*/
class RedisCacheLockTest extends LockTestCase
class RedisCacheLockTest extends CacheLockTestCase
{
protected function getInstance()
protected function setUp(): void
{
$configMock = Mockery::mock(IManageConfigValues::class);
@ -45,15 +46,23 @@ class RedisCacheLockTest extends LockTestCase
->with('system', 'redis_password')
->andReturn(null);
$lock = null;
try {
$cache = new RedisCache($host, $configMock);
$lock = new CacheLock($cache);
$this->cache = new RedisCache($host, $configMock);
$this->lock = new CacheLock($this->cache);
} catch (Exception $e) {
static::markTestSkipped('Redis is not available. Error: ' . $e->getMessage());
}
return $lock;
parent::setUp();
}
protected function getInstance(): CAcheLock
{
return $this->lock;
}
protected function getCache(): ICanCacheInMemory
{
return $this->cache;
}
}

View file

@ -12,6 +12,7 @@ use Friendica\App;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Config\Model\ReadOnlyFileConfig;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Core\Lock\Type\SemaphoreLock;
use Friendica\Core\System;
use Friendica\DI;
@ -31,7 +32,7 @@ class SemaphoreLockTest extends LockTestCase
$dice->shouldReceive('create')->with(App::class)->andReturn($app);
$configCache = new Cache(['system' => ['temppath' => '/tmp']]);
$configMock = new ReadOnlyFileConfig($configCache);
$configMock = new ReadOnlyFileConfig($configCache);
$dice->shouldReceive('create')->with(IManageConfigValues::class)->andReturn($configMock);
// @todo Because "get_temppath()" is using static methods, we have to initialize the BaseObject
@ -40,7 +41,7 @@ class SemaphoreLockTest extends LockTestCase
parent::setUp();
}
protected function getInstance()
protected function getInstance(): ICanLock
{
return new SemaphoreLock();
}

View file

@ -17,16 +17,16 @@ class SyslogLoggerFactoryWrapper extends SyslogLogger
{
public function create(IManageConfigValues $config): LoggerInterface
{
$logOpts = $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS;
$logFacility = $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY;
$logOpts = (int) $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS;
$logFacility = (int) $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY;
$loglevel = SyslogLogger::mapLegacyConfigDebugLevel($config->get('system', 'loglevel'));
if (array_key_exists($loglevel, SyslogLoggerClass::logLevels)) {
$loglevel = SyslogLoggerClass::logLevels[$loglevel];
} else {
if (!array_key_exists($loglevel, SyslogLoggerClass::logLevels)) {
throw new LogLevelException(sprintf('The level "%s" is not valid.', $loglevel));
}
$loglevel = SyslogLoggerClass::logLevels[$loglevel];
return new SyslogLoggerWrapper($this->channel, $this->introspection, $loglevel, $logOpts, $logFacility);
}
}

View file

@ -17,7 +17,7 @@ class SyslogLoggerWrapper extends SyslogLogger
{
private $content;
public function __construct(string $channel, IHaveCallIntrospections $introspection, string $logLevel, string $logOptions, string $logFacility)
public function __construct(string $channel, IHaveCallIntrospections $introspection, int $logLevel, int $logOptions, int $logFacility)
{
parent::__construct($channel, $introspection, $logLevel, $logOptions, $logFacility);

View file

@ -152,13 +152,13 @@ class UserSessionTest extends MockedTestCase
'data' => [
'remote' => ['3' => '21'],
],
'expected' => false,
'expected' => 0,
],
'empty' => [
'cid' => 21,
'data' => [
],
'expected' => false,
'expected' => 0,
],
];
}
@ -167,7 +167,7 @@ class UserSessionTest extends MockedTestCase
public function testGetUserIdForVisitorContactID(int $cid, array $data, $expected)
{
$userSession = new UserSession(new ArraySession($data));
$this->assertEquals($expected, $userSession->getUserIDForVisitorContactID($cid));
$this->assertSame($expected, $userSession->getUserIDForVisitorContactID($cid));
}
public function dataAuthenticated()

View file

@ -23,12 +23,13 @@ use Friendica\Core\Storage\Type\SystemResource;
use Friendica\Database\Database;
use Friendica\DI;
use Friendica\Core\Config\Factory\Config;
use Friendica\Core\Hooks\HookEventBridge;
use Friendica\Core\Storage\Type;
use Friendica\Test\DatabaseTestCase;
use Friendica\Test\Util\CreateDatabaseTrait;
use Friendica\Test\Util\Database\StaticDatabase;
use Friendica\Test\Util\FakeEventDispatcher;
use org\bovigo\vfs\vfsStream;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Friendica\Test\Util\SampleStorageBackend;
@ -38,8 +39,6 @@ class StorageManagerTest extends DatabaseTestCase
/** @var IManageConfigValues */
private $config;
/** @var LoggerInterface */
private $logger;
/** @var L10n */
private $l10n;
@ -56,7 +55,6 @@ class StorageManagerTest extends DatabaseTestCase
vfsStream::newDirectory(Type\FilesystemConfig::DEFAULT_BASE_FOLDER, 0777)->at($this->root);
$this->logger = new NullLogger();
$this->database = $this->getDbInstance();
$configFactory = new Config();
@ -87,7 +85,14 @@ class StorageManagerTest extends DatabaseTestCase
*/
public function testInstance()
{
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
self::assertInstanceOf(StorageManager::class, $storageManager);
}
@ -149,7 +154,14 @@ class StorageManagerTest extends DatabaseTestCase
$this->config->set('storage', 'name', $name);
}
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
if ($interface === ICanWriteToStorage::class) {
$storage = $storageManager->getWritableStorageByName($name);
@ -169,7 +181,14 @@ class StorageManagerTest extends DatabaseTestCase
*/
public function testIsValidBackend($name, $valid, $interface, $assert, $assertName)
{
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
// true in every of the backends
self::assertEquals(!empty($assertName), $storageManager->isValidBackend($name));
@ -183,7 +202,14 @@ class StorageManagerTest extends DatabaseTestCase
*/
public function testListBackends()
{
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
self::assertEquals(StorageManager::DEFAULT_BACKENDS, $storageManager->listBackends());
}
@ -199,7 +225,14 @@ class StorageManagerTest extends DatabaseTestCase
static::markTestSkipped('only works for ICanWriteToStorage');
}
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
$selBackend = $storageManager->getWritableStorageByName($name);
$storageManager->setBackend($selBackend);
@ -219,7 +252,14 @@ class StorageManagerTest extends DatabaseTestCase
$this->expectException(InvalidClassStorageException::class);
}
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
self::assertInstanceOf($assert, $storageManager->getBackend());
}
@ -240,7 +280,14 @@ class StorageManagerTest extends DatabaseTestCase
->addRule(IHandleSessions::class, ['instanceOf' => Memory::class, 'shared' => true, 'call' => null]);
DI::init($dice);
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
self::assertTrue($storageManager->register(SampleStorageBackend::class));
@ -268,7 +315,21 @@ class StorageManagerTest extends DatabaseTestCase
->addRule(IHandleSessions::class, ['instanceOf' => Memory::class, 'shared' => true, 'call' => null]);
DI::init($dice);
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
/** @var \Friendica\Event\EventDispatcher */
$eventDispatcher = DI::eventDispatcher();
foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) {
$eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]);
}
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
$eventDispatcher,
$this->l10n,
false
);
self::assertTrue($storageManager->register(SampleStorageBackend::class));
@ -307,8 +368,15 @@ class StorageManagerTest extends DatabaseTestCase
$this->loadFixture(__DIR__ . '/../../../../datasets/storage/database.fixture.php', $this->database);
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storage = $storageManager->getWritableStorageByName($name);
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
$storage = $storageManager->getWritableStorageByName($name);
$storageManager->move($storage);
$photos = $this->database->select('photo', ['backend-ref', 'backend-class', 'id', 'data']);
@ -331,8 +399,15 @@ class StorageManagerTest extends DatabaseTestCase
$this->expectException(InvalidClassStorageException::class);
$this->expectExceptionMessage('Backend SystemResource is not valid');
$storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false);
$storage = $storageManager->getWritableStorageByName(SystemResource::getName());
$storageManager = new StorageManager(
$this->database,
$this->config,
new NullLogger(),
new FakeEventDispatcher(),
$this->l10n,
false
);
$storage = $storageManager->getWritableStorageByName(SystemResource::getName());
$storageManager->move($storage);
}
}

View file

@ -0,0 +1,203 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
namespace Friendica\Test\src\Module;
use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Type\ArrayCache;
use Friendica\Core\Cache\Type\DatabaseCache;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Core\Lock\Type\CacheLock;
use Friendica\Core\Lock\Type\DatabaseLock;
use Friendica\DI;
use Friendica\Module\Special\HTTPException;
use Friendica\Module\StatsCaching;
use Friendica\Test\FixtureTestCase;
use Mockery\MockInterface;
use phpmock\mockery\PHPMockery;
class StatsCachingTest extends FixtureTestCase
{
/** @var MockInterface|HTTPException */
protected $httpExceptionMock;
protected ICanCache $cache;
protected ICanLock $lock;
/** @var MockInterface|IManageConfigValues */
protected $config;
protected function setUp(): void
{
parent::setUp();
$this->httpExceptionMock = \Mockery::mock(HTTPException::class);
$this->config = \Mockery::mock(IManageConfigValues::class);
$this->cache = new ArrayCache('localhost');
$this->lock = new CacheLock($this->cache);
}
public function testStatsCachingNotAllowed()
{
$this->httpExceptionMock->shouldReceive('content')->andReturn('failed')->once();
$response = (new StatsCaching(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], $this->config, $this->cache, $this->lock, []))
->run($this->httpExceptionMock);
self::assertEquals('404', $response->getStatusCode());
self::assertEquals('Page not found', $response->getReasonPhrase());
self::assertEquals('failed', $response->getBody());
}
public function testStatsCachingWitMinimumCache()
{
$request = [
'key' => '12345',
];
$this->config->shouldReceive('get')->with('system', 'stats_key')->twice()->andReturn('12345');
PHPMockery::mock("Friendica\\Module", "function_exists")->with('opcache_get_status')->once()->andReturn(false);
$response = (new StatsCaching(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], $this->config, $this->cache, $this->lock, []))
->run($this->httpExceptionMock, $request);
self::assertJson($response->getBody());
self::assertEquals(['Content-type' => ['application/json; charset=utf-8'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
$json = json_decode($response->getBody(), true);
self::assertEquals([
'type' => 'array',
'stats' => [],
], $json['cache']);
self::assertEquals([
'type' => 'array',
'stats' => [],
], $json['lock']);
}
public function testStatsCachingWithDatabase()
{
$request = [
'key' => '12345',
];
$this->config->shouldReceive('get')->with('system', 'stats_key')->twice()->andReturn('12345');
$this->cache = new DatabaseCache('localhost', DI::dba());
$this->lock = new DatabaseLock(DI::dba());
PHPMockery::mock("Friendica\\Module", "function_exists")->with('opcache_get_status')->once()->andReturn(false);
$response = (new StatsCaching(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], $this->config, $this->cache, $this->lock, []))
->run($this->httpExceptionMock, $request);
self::assertJson($response->getBody());
self::assertEquals(['Content-type' => ['application/json; charset=utf-8'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
$json = json_decode($response->getBody(), true);
self::assertEquals(['enabled' => false], $json['opcache']);
self::assertEquals(['type' => 'database'], $json['cache']);
self::assertEquals(['type' => 'database'], $json['lock']);
}
public function testStatsCachingWithCache()
{
$request = [
'key' => '12345',
];
$this->config->shouldReceive('get')->with('system', 'stats_key')->twice()->andReturn('12345');
$this->cache = new DatabaseCache('localhost', DI::dba());
$this->lock = new DatabaseLock(DI::dba());
PHPMockery::mock("Friendica\\Module", "function_exists")->with('opcache_get_status')->once()->andReturn(false);
$response = (new StatsCaching(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], $this->config, $this->cache, $this->lock, []))
->run($this->httpExceptionMock, $request);
self::assertJson($response->getBody());
self::assertEquals(['Content-type' => ['application/json; charset=utf-8'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
$json = json_decode($response->getBody(), true);
self::assertEquals(['enabled' => false], $json['opcache']);
self::assertEquals(['type' => 'database'], $json['cache']);
self::assertEquals(['type' => 'database'], $json['lock']);
}
public function testStatsCachingWithOpcacheAndNull()
{
$request = [
'key' => '12345',
];
$this->config->shouldReceive('get')->with('system', 'stats_key')->twice()->andReturn('12345');
$this->cache = new DatabaseCache('localhost', DI::dba());
$this->lock = new DatabaseLock(DI::dba());
PHPMockery::mock("Friendica\\Module", "function_exists")->with('opcache_get_status')->once()->andReturn(true);
PHPMockery::mock("Friendica\\Module", "opcache_get_status")->with(false)->once()->andReturn(false);
$response = (new StatsCaching(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], $this->config, $this->cache, $this->lock, []))
->run($this->httpExceptionMock, $request);
self::assertJson($response->getBody());
self::assertEquals(['Content-type' => ['application/json; charset=utf-8'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
$json = json_decode($response->getBody(), true);
self::assertEquals([
'enabled' => false,
'hit_rate' => null,
'used_memory' => null,
'free_memory' => null,
'num_cached_scripts' => null,
], $json['opcache']);
self::assertEquals(['type' => 'database'], $json['cache']);
self::assertEquals(['type' => 'database'], $json['lock']);
}
public function testStatsCachingWithOpcacheAndValues()
{
$request = [
'key' => '12345',
];
$this->config->shouldReceive('get')->with('system', 'stats_key')->twice()->andReturn('12345');
$this->cache = new DatabaseCache('localhost', DI::dba());
$this->lock = new DatabaseLock(DI::dba());
PHPMockery::mock("Friendica\\Module", "function_exists")->with('opcache_get_status')->once()->andReturn(true);
PHPMockery::mock("Friendica\\Module", "opcache_get_status")->with(false)->once()->andReturn([
'opcache_enabled' => true,
'opcache_statistics' => [
'opcache_hit_rate' => 1,
'num_cached_scripts' => 2,
],
'memory_usage' => [
'used_memory' => 3,
'free_memory' => 4,
]
]);
$response = (new StatsCaching(DI::l10n(), DI::baseUrl(), DI::args(), DI::logger(), DI::profiler(), DI::apiResponse(), [], $this->config, $this->cache, $this->lock, []))
->run($this->httpExceptionMock, $request);
self::assertJson($response->getBody());
self::assertEquals(['Content-type' => ['application/json; charset=utf-8'], ICanCreateResponses::X_HEADER => ['json']], $response->getHeaders());
$json = json_decode($response->getBody(), true);
self::assertEquals([
'enabled' => true,
'hit_rate' => 1,
'used_memory' => 3,
'free_memory' => 4,
'num_cached_scripts' => 2,
], $json['opcache']);
self::assertEquals(['type' => 'database'], $json['cache']);
self::assertEquals(['type' => 'database'], $json['lock']);
}
}