diff options
-rw-r--r-- | Zotlabs/Lib/QueueWorker.php | 38 | ||||
-rw-r--r-- | include/channel.php | 4 | ||||
-rw-r--r-- | include/plugin.php | 21 | ||||
-rw-r--r-- | tests/unit/Access/PermissionsTest.php | 26 | ||||
-rw-r--r-- | tests/unit/CallHooksTest.php | 65 | ||||
-rw-r--r-- | tests/unit/CreateIdentityTest.php | 65 | ||||
-rw-r--r-- | tests/unit/Lib/PermissionDescriptionTest.php | 20 |
7 files changed, 157 insertions, 82 deletions
diff --git a/Zotlabs/Lib/QueueWorker.php b/Zotlabs/Lib/QueueWorker.php index ce239809f..24114438e 100644 --- a/Zotlabs/Lib/QueueWorker.php +++ b/Zotlabs/Lib/QueueWorker.php @@ -6,6 +6,8 @@ use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Exception\UnableToBuildUuidException; use Zotlabs\Lib\Config; +require_once 'include/dba/dba_transaction.php'; + class QueueWorker { public static $queueworker = null; @@ -29,18 +31,6 @@ class QueueWorker { 'Expire' ]; - private static function qstart() { - q('START TRANSACTION'); - } - - private static function qcommit() { - q("COMMIT"); - } - - private static function qrollback() { - q("ROLLBACK"); - } - public static function Summon($argv) { if ($argv[0] !== 'Queueworker') { @@ -66,7 +56,7 @@ class QueueWorker { logger('queueworker_stats_summon: cmd:' . $argv[0] . ' ' . 'timestamp:' . time()); - self::qstart(); + $transaction = new \DbaTransaction(\DBA::$dba); $r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')", intval($priority), $workinfo_json, @@ -74,11 +64,11 @@ class QueueWorker { dbesc($argv[0]) ); if (!$r) { - self::qrollback(); + // Transaction is autmatically rolled back on return logger("INSERT FAILED", LOGGER_DEBUG); return; } - self::qcommit(); + $transaction->commit(); logger('INSERTED: ' . $workinfo_json, LOGGER_DEBUG); } @@ -112,7 +102,7 @@ class QueueWorker { return; } - self::qstart(); + $transaction = new \DbaTransaction(\DBA::$dba); $r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')", intval($priority), $workinfo_json, @@ -120,11 +110,11 @@ class QueueWorker { dbesc($argv[0]) ); if (!$r) { - self::qrollback(); + // Transaction is automatically rolled back on return logger("Insert failed: " . $workinfo_json, LOGGER_DEBUG); return; } - self::qcommit(); + $transaction->commit(); logger('INSERTED: ' . $workinfo_json, LOGGER_DEBUG); } @@ -141,7 +131,7 @@ class QueueWorker { self::$workermaxage = self::$workermaxage > 120 ? self::$workermaxage : 300; } - self::qstart(); + $transaction = new \DbaTransaction(\DBA::$dba); // skip locked is preferred but is not supported by mariadb < 10.6 which is still used a lot - hence make it optional $sql_quirks = ((Config::Get('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT'); @@ -159,7 +149,7 @@ class QueueWorker { $u = dbq("update workerq set workerq_reservationid = null where workerq_id in ($ids)"); } - self::qcommit(); + $transaction->commit(); //q("update workerq set workerq_reservationid = null where workerq_reservationid is not null and workerq_processtimeout < %s", //db_utcnow() @@ -197,7 +187,7 @@ class QueueWorker { private static function getWorkId() { self::GetWorkerCount(); - self::qstart(); + $transaction = new \DbaTransaction(\DBA::$dba); // skip locked is preferred but is not supported by mariadb < 10.6 which is still used a lot - hence make it optional $sql_quirks = ((Config::Get('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT'); @@ -205,7 +195,7 @@ class QueueWorker { $work = dbq("SELECT workerq_id, workerq_cmd FROM workerq WHERE workerq_reservationid IS NULL ORDER BY workerq_priority DESC, workerq_id ASC LIMIT 1 FOR UPDATE $sql_quirks"); if (!$work) { - self::qrollback(); + // Transaction automatically rolled back on return return false; } @@ -225,13 +215,13 @@ class QueueWorker { ); if (!$work) { - self::qrollback(); + // Transaction automatically rolled back on return logger("Could not update workerq.", LOGGER_DEBUG); return false; } logger("GOTWORK: " . json_encode($work), LOGGER_DEBUG); - self::qcommit(); + $transaction->commit(); return $id; } diff --git a/include/channel.php b/include/channel.php index 568ad052a..22b5bcde1 100644 --- a/include/channel.php +++ b/include/channel.php @@ -199,8 +199,8 @@ function create_identity($arr) { $ret = array('success' => false); - if(! $arr['account_id']) { - $ret['message'] = t('No account identifier'); + if(empty($arr['account_id'])) { + $ret['message'] = t('No account identifier'); return $ret; } $ret = identity_check_service_class($arr['account_id']); diff --git a/include/plugin.php b/include/plugin.php index 4601cb544..62b643c3e 100644 --- a/include/plugin.php +++ b/include/plugin.php @@ -488,18 +488,19 @@ function call_hooks($name, &$data = null) { @include_once($hook[0]); } - if(preg_match('|^a:[0-9]+:{.*}$|s', $hook[1])) { - $hook[1] = unserialize($hook[1]); - } - elseif(strpos($hook[1],'::')) { - // We shouldn't need to do this, but it appears that PHP - // isn't able to directly execute a string variable with a class - // method in the manner we are attempting it, so we'll - // turn it into an array. - $hook[1] = explode('::',$hook[1]); + if(is_string($hook[1])) { + if (preg_match('|^a:[0-9]+:{.*}$|s', $hook[1])) { + $hook[1] = unserialize($hook[1]); + } + elseif(strpos($hook[1],'::')) { + // We shouldn't need to do this, but it appears that PHP + // isn't able to directly execute a string variable with a class + // method in the manner we are attempting it, so we'll + // turn it into an array. + $hook[1] = explode('::',$hook[1]); + } } - if(is_callable($hook[1])) { $func = $hook[1]; $func($data); diff --git a/tests/unit/Access/PermissionsTest.php b/tests/unit/Access/PermissionsTest.php index dd001e68a..f9cb25b64 100644 --- a/tests/unit/Access/PermissionsTest.php +++ b/tests/unit/Access/PermissionsTest.php @@ -63,14 +63,6 @@ class PermissionsTest extends UnitTestCase { // There are 17 default perms $permsCount = 17; - // Create a stub for global function t() with expectation - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $t->expects($this->exactly(2*$permsCount))->willReturnCallback( - function ($string) { - return $string; - } - ); - // static method Perms() $perms = Permissions::Perms(); @@ -97,14 +89,6 @@ class PermissionsTest extends UnitTestCase { // There are 17 default perms $permsCount = 17; - // Create a stub for global function t() with expectation - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $t->expects($this->exactly(2*$permsCount))->willReturnCallback( - function ($string) { - return $string; - } - ); - $perms = Permissions::Perms('view_'); $this->assertEquals($permsCount, count($perms)); @@ -125,9 +109,6 @@ class PermissionsTest extends UnitTestCase { * @param array $expected The expected result perms array */ public function testFilledPerms($permarr, $expected) { - // Create a stub for global function t() - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $this->assertEquals($expected, Permissions::FilledPerms($permarr)); } /** @@ -209,13 +190,6 @@ class PermissionsTest extends UnitTestCase { * @uses ::call_hooks */ public function testFilledPermsNull() { - // Create a stub for global function t() with expectation - $t = $this->getFunctionMock('Zotlabs\Access', 't'); - $t->expects($this->atLeastOnce()); - // Create a stub for global function bt() with expectations - $bt = $this->getFunctionMock('Zotlabs\Access', 'btlogger'); - $bt->expects($this->once())->with($this->equalTo('FilledPerms: null')); - $result = [ 'view_stream' => 0, 'send_stream' => 0, diff --git a/tests/unit/CallHooksTest.php b/tests/unit/CallHooksTest.php new file mode 100644 index 000000000..0170f31d0 --- /dev/null +++ b/tests/unit/CallHooksTest.php @@ -0,0 +1,65 @@ +<?php +/** + * Unit tests for the `call_hooks` function, located in include/plugin.php. + * + * SPDX-FileCopyrightText: 2024 Hubzilla Community + * SPDX-FileContributor: Harald Eilertsen + * + * SPDX-License-Identifier: MIT + */ + +namespace Zotlabs\Tests\Unit; + +use PHPUnit\Framework\Attributes\BackupStaticProperties; +use App; + +#[BackupStaticProperties(App::class)] +class CallHooksTest extends UnitTestCase { + + /** + * Test using a freestanding function as callback. + * + * @SuppressWarnings(PHPMD.EvalExpression) + */ + public function test_freestanding_function_as_string(): void { + eval('function hook_test_function(array &$args): void { $args["called"] = true; }'); + insert_hook('test_hook', 'hook_test_function'); + $this->assertHookInvoked(); + } + + public function test_static_class_function_as_string(): void { + insert_hook('test_hook', 'Zotlabs\Tests\Unit\CallHooksTest::static_test_hook'); + $this->assertHookInvoked(); + } + + public function test_static_class_function_as_array(): void { + insert_hook('test_hook', ['Zotlabs\Tests\Unit\CallHooksTest', 'static_test_hook']); + $this->assertHookInvoked(); + } + + public function test_static_class_function_as_serialized_array(): void { + insert_hook('test_hook', serialize(['Zotlabs\Tests\Unit\CallHooksTest', 'static_test_hook'])); + $this->assertHookInvoked(); + } + + public function test_instance_function_as_array(): void { + insert_hook('test_hook', [$this, 'instance_test_hook']); + $this->assertHookInvoked(); + } + + + public function assertHookInvoked(): void { + $test_hook_args = ['called' => false]; + call_hooks('test_hook', $test_hook_args); + + $this->assertTrue($test_hook_args['called']); + } + + public function instance_test_hook(array &$args): void { + $args['called'] = true; + } + public static function static_test_hook(array &$args): void { + $args['called'] = true; + } +} + diff --git a/tests/unit/CreateIdentityTest.php b/tests/unit/CreateIdentityTest.php new file mode 100644 index 000000000..a5e0f278a --- /dev/null +++ b/tests/unit/CreateIdentityTest.php @@ -0,0 +1,65 @@ +<?php +/** + * Unit tests for the `create_identity` function. + * + * SPDX-FileCopyrightText: 2024 Hubzilla Community + * SPDX-FileContributor: Harald Eilertsen + * + * SPDX-License-Identifier: MIT + */ + +namespace Zotlabs\Tests\Unit; + +class CreateIdentityTest extends UnitTestCase { + + private bool $queueworker_started = false; + + public function test_empty_args() { + insert_hook('proc_run', [$this, 'proc_run_hook']); + $result = create_identity([]); + $this->assertEquals( + ['success' => false, 'message' => 'No account identifier'], + $result); + + $this->assertFalse($this->queueworker_started); + } + + public function test_create_new_channel_with_valid_account_id(): void { + insert_hook('proc_run', [$this, 'proc_run_hook']); + $result = create_identity([ + 'account_id' => $this->fixtures['account'][0]['account_id'], + 'nickname' => 'testuser', + 'name' => 'Olga Testuser', + ]); + + $this->assertTrue($result['success']); + $this->assertTrue($this->queueworker_started); + } + + public function test_create_new_channel_with_nnexistant_account_id(): void { + insert_hook('proc_run', [$this, 'proc_run_hook']); + $result = create_identity([ + 'account_id' => 666, + 'nickname' => 'testuser', + 'name' => 'Olga Testuser', + ]); + + /* + * We would expect this fo fail, but... + * + * The create_identity function will happily create a new channel with an + * non-existent account_id. The New_channel module will perform a check + * to ensure that only valid (and logged in) accounts can create a new channel. + * + * This is a bit weak, but for now we let it pass... + */ + $this->assertTrue($result['success']); + $this->assertTrue($this->queueworker_started); + } + + public function proc_run_hook(array &$args): void { + $args['run_cmd'] = false; + $this->queueworker_started = + $args['args'] === ['php', 'Zotlabs/Daemon/Master.php', 'Queueworker']; + } +} diff --git a/tests/unit/Lib/PermissionDescriptionTest.php b/tests/unit/Lib/PermissionDescriptionTest.php index fdd676f61..1e4b5292c 100644 --- a/tests/unit/Lib/PermissionDescriptionTest.php +++ b/tests/unit/Lib/PermissionDescriptionTest.php @@ -46,16 +46,6 @@ class PermissionDescriptionTest extends UnitTestCase { } public function testFromStandalonePermission() { - // Create a stub for global function t() - $t = $this->getFunctionMock('Zotlabs\Lib', 't'); - $t->expects($this->atLeastOnce())->willReturnCallback( - function ($string) { - return $string; - } - ); - // Create a mock for global function logger() - $this->getFunctionMock('Zotlabs\Lib', 'logger'); - $permDescUnknown = PermissionDescription::fromStandalonePermission(-1); $permDescSelf = PermissionDescription::fromStandalonePermission(0); @@ -113,16 +103,6 @@ class PermissionDescriptionTest extends UnitTestCase { } public function testGetPermissionDescription() { - // Create a stub for global function t() - $t = $this->getFunctionMock('Zotlabs\Lib', 't'); - $t->expects($this->atLeastOnce())->willReturnCallback( - function ($string) { - return $string; - } - ); - // Create a mock for global function logger() - $this->getFunctionMock('Zotlabs\Lib', 'logger'); - // Create a stub for the PermissionDescription class $stub = $this->createMock(PermissionDescription::class); $stub->method('get_permission_description') |