diff --git a/lib/Service.php b/lib/Service.php index bd02fc9..ed234d6 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -12,18 +12,14 @@ class Service { const DRIVER_NAMES = [ 'serial' => \JKingWeb\Arsse\Service\Serial\Driver::class, 'subprocess' => \JKingWeb\Arsse\Service\Subprocess\Driver::class, - 'curl' => \JKingWeb\Arsse\Service\Curl\Driver::class, ]; /** @var Service\Driver */ protected $drv; - /** @var \DateInterval */ - protected $interval; public function __construct() { $driver = Arsse::$conf->serviceDriver; $this->drv = new $driver(); - $this->interval = Arsse::$conf->serviceFrequency; } public function watch(bool $loop = true): \DateTimeInterface { @@ -34,12 +30,12 @@ class Service { $list = Arsse::$db->feedListStale(); if ($list) { $this->drv->queue(...$list); + unset($list); $this->drv->exec(); $this->drv->clean(); - unset($list); } static::cleanupPost(); - $t->add($this->interval); + $t->add(Arsse::$conf->serviceFrequency); // @codeCoverageIgnoreStart if ($loop) { do { diff --git a/lib/Service/Driver.php b/lib/Service/Driver.php index 0f63383..e2dcf92 100644 --- a/lib/Service/Driver.php +++ b/lib/Service/Driver.php @@ -11,5 +11,5 @@ interface Driver { public static function requirementsMet(): bool; public function queue(int ...$feeds): int; public function exec(): int; - public function clean(): bool; + public function clean(): int; } diff --git a/lib/Service/Serial/Driver.php b/lib/Service/Serial/Driver.php index df3580c..dc2c74f 100644 --- a/lib/Service/Serial/Driver.php +++ b/lib/Service/Serial/Driver.php @@ -36,8 +36,9 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - public function clean(): bool { + public function clean(): int { + $out = sizeof($this->queue); $this->queue = []; - return true; + return $out; } } diff --git a/lib/Service/Subprocess/Driver.php b/lib/Service/Subprocess/Driver.php index 5e79ed0..0986f2c 100644 --- a/lib/Service/Subprocess/Driver.php +++ b/lib/Service/Subprocess/Driver.php @@ -33,7 +33,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { $id = (int) array_shift($this->queue); $php = escapeshellarg(\PHP_BINARY); $arsse = escapeshellarg($_SERVER['argv'][0]); - array_push($pp, popen("$php $arsse feed refresh $id", "r")); + array_push($pp, $this->execCmd("$php $arsse feed refresh $id")); } while ($pp) { $p = array_pop($pp); @@ -43,8 +43,14 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - public function clean(): bool { + /** @codeCoverageIgnore */ + protected function execCmd(string $cmd) { + return popen($cmd, "r"); + } + + public function clean(): int { + $out = sizeof($this->queue); $this->queue = []; - return true; + return $out; } } diff --git a/tests/cases/Service/TestSerial.php b/tests/cases/Service/TestSerial.php new file mode 100644 index 0000000..5a96078 --- /dev/null +++ b/tests/cases/Service/TestSerial.php @@ -0,0 +1,47 @@ +assertTrue(Driver::requirementsMet()); + $this->assertInstanceOf(DriverInterface::class, new Driver); + } + + public function testFetchDriverName() { + $this->assertTrue(strlen(Driver::driverName()) > 0); + } + + public function testEnqueueFeeds() { + $d = new Driver; + $this->assertSame(3, $d->queue(1, 2, 3)); + $this->assertSame(5, $d->queue(4, 5)); + $this->assertSame(5, $d->clean()); + $this->assertSame(1, $d->queue(5)); + } + + public function testRefreshFeeds() { + $d = new Driver; + $d->queue(1, 4, 3); + $this->assertSame(Arsse::$conf->serviceQueueWidth, $d->exec()); + \Phake::verify(Arsse::$db)->feedUpdate(1); + \Phake::verify(Arsse::$db)->feedUpdate(4); + \Phake::verify(Arsse::$db)->feedUpdate(3); + } +} diff --git a/tests/cases/Service/TestService.php b/tests/cases/Service/TestService.php index a1db862..102a9ce 100644 --- a/tests/cases/Service/TestService.php +++ b/tests/cases/Service/TestService.php @@ -59,4 +59,25 @@ class TestService extends \JKingWeb\Arsse\Test\AbstractTest { \Phake::verify(Arsse::$db)->articleCleanup(); \Phake::verify(Arsse::$db)->driverMaintenance(); } + + public function testRefreshFeeds() { + // set up mock database actions + \Phake::when(Arsse::$db)->metaSet->thenReturn(true); + \Phake::when(Arsse::$db)->feedCleanup->thenReturn(true); + \Phake::when(Arsse::$db)->sessionCleanup->thenReturn(true); + \Phake::when(Arsse::$db)->articleCleanup->thenReturn(0); + \Phake::when(Arsse::$db)->feedListStale->thenReturn([1,2,3]); + // perform the test + $d = \Phake::mock(\JKingWeb\Arsse\Service\Driver::class); + $s = new \JKingWeb\Arsse\Test\Service($d); + $this->assertInstanceOf(\DateTimeInterface::class, $s->watch(false)); + // verify invocations + \Phake::verify($d)->queue(1, 2, 3); + \Phake::verify($d)->exec(); + \Phake::verify($d)->clean(); + \Phake::verify(Arsse::$db)->feedCleanup(); + \Phake::verify(Arsse::$db)->sessionCleanup(); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db)->metaSet("service_last_checkin", $this->anything(), "datetime"); + } } diff --git a/tests/cases/Service/TestSubprocess.php b/tests/cases/Service/TestSubprocess.php new file mode 100644 index 0000000..c02c4b2 --- /dev/null +++ b/tests/cases/Service/TestSubprocess.php @@ -0,0 +1,48 @@ +assertTrue(Driver::requirementsMet()); + $this->assertInstanceOf(DriverInterface::class, new Driver); + } + + public function testFetchDriverName() { + $this->assertTrue(strlen(Driver::driverName()) > 0); + } + + public function testEnqueueFeeds() { + $d = new Driver; + $this->assertSame(3, $d->queue(1, 2, 3)); + $this->assertSame(5, $d->queue(4, 5)); + $this->assertSame(5, $d->clean()); + $this->assertSame(1, $d->queue(5)); + } + + public function testRefreshFeeds() { + $d = \Phake::partialMock(Driver::class); + \Phake::when($d)->execCmd->thenReturnCallback(function(string $cmd) { + // FIXME: Does this work in Windows? + return popen("echo ".escapeshellarg($cmd), "r"); + }); + $this->assertSame(3, $d->queue(1, 4, 3)); + $this->assertSame(Arsse::$conf->serviceQueueWidth, $d->exec()); + \Phake::verify($d, \Phake::times(3))->execCmd; + } +} diff --git a/tests/cases/TestArsse.php b/tests/cases/TestArsse.php index 179f399..f28e7ee 100644 --- a/tests/cases/TestArsse.php +++ b/tests/cases/TestArsse.php @@ -37,6 +37,9 @@ class TestArsse extends \JKingWeb\Arsse\Test\AbstractTest { } public function testLoadNewData() { + if (!\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet() && !\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) { + $this->markTestSkipped("A functional SQLite interface is required for this test"); + } $conf = (new Conf)->import(['dbSQLite3File' => ":memory:"]); Arsse::load($conf); $this->assertInstanceOf(Conf::class, Arsse::$conf); diff --git a/tests/lib/Service.php b/tests/lib/Service.php new file mode 100644 index 0000000..cfd11f4 --- /dev/null +++ b/tests/lib/Service.php @@ -0,0 +1,13 @@ +drv = $drv; + } +} diff --git a/tests/phpunit.dist.xml b/tests/phpunit.dist.xml index dd2ba50..997c6a7 100644 --- a/tests/phpunit.dist.xml +++ b/tests/phpunit.dist.xml @@ -128,6 +128,8 @@ cases/Service/TestService.php + cases/Service/TestSerial.php + cases/Service/TestSubprocess.php cases/CLI/TestCLI.php cases/TestArsse.php