postgres icon indicating copy to clipboard operation
postgres copied to clipboard

Amp\Loop\InvalidWatcherError : Cannot reference an invalid watcher identifier: 'e'

Open PNixx opened this issue 3 years ago • 3 comments

I try use PHPUnit with Postgres adapter. But I catch error. amphp/postgres v1.4.3 Example code:

<?php
use Amp\PHPUnit\AsyncTestCase;
use Amp\Postgres\ConnectionConfig;

$connection = \Amp\Postgres\pool(ConnectionConfig::fromString("host=localhost port=5432 dbname=rees46_test user=rails password=rails"), 5);

class BarTest extends AsyncTestCase {

	public function test() {
		global $connection;

		$result = yield $connection->execute('SELECT 1 AS c');
		if( yield $result->advance() ) {
			$this->assertSame(1, $result->getCurrent()['c']);
		}
	}
	public function test2() {
		global $connection;

		$result = yield $connection->execute('SELECT 1 AS c');
		if( yield $result->advance() ) {
			$this->assertSame(1, $result->getCurrent()['c']);
		}
	}
}

Test log:

Testing started at 23:04 ...
PHPUnit 9.5.11 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.0.12
Configuration: /project/phpunit.xml

Amp\Loop\InvalidWatcherError : Cannot reference an invalid watcher identifier: 'e'
 /project/vendor/amphp/amp/lib/Loop/Driver.php:516
 /project/vendor/amphp/amp/lib/Loop.php:322
 /project/vendor/amphp/postgres/src/PgSqlHandle.php:269
 /project/vendor/amphp/postgres/src/PgSqlHandle.php:381
 /project/vendor/amphp/amp/lib/Coroutine.php:67
 /project/vendor/amphp/amp/lib/functions.php:96
 /project/vendor/amphp/postgres/src/PgSqlHandle.php:382
 /project/vendor/amphp/postgres/src/Connection.php:79
 /project/vendor/amphp/postgres/src/Connection.php:109
 /project/vendor/amphp/postgres/src/Pool.php:83
 /project/vendor/amphp/sql-common/src/ConnectionPool.php:363
 /project/vendor/amphp/amp/lib/Coroutine.php:67
 /project/vendor/amphp/amp/lib/functions.php:96
 /project/vendor/amphp/sql-common/src/ConnectionPool.php:382
 /project/test/BarTest.php:21
 /project/vendor/amphp/amp/lib/Coroutine.php:67
 /project/vendor/amphp/phpunit-util/src/AsyncTestCase.php:278
 /project/vendor/amphp/phpunit-util/src/AsyncTestCase.php:137
 /project/vendor/amphp/amp/lib/Coroutine.php:118
 /project/vendor/amphp/amp/lib/Success.php:41
 /project/vendor/amphp/amp/lib/Coroutine.php:151
 /project/vendor/amphp/phpunit-util/src/AsyncTestCase.php:68
 /project/vendor/amphp/amp/lib/Loop/Driver.php:119
 /project/vendor/amphp/amp/lib/Loop/Driver.php:72
 /project/vendor/amphp/amp/lib/Loop/EventDriver.php:211
 /project/vendor/amphp/amp/lib/Loop.php:95
 /project/vendor/amphp/phpunit-util/src/AsyncTestCase.php:96
 /project/vendor/amphp/phpunit-util/src/AsyncTestCase.php:46

Time: 00:00.110, Memory: 10.00 MB

ERRORS!
Tests: 2, Assertions: 1, Errors: 1.

But for this example, tests works correctly:

<?php
use Amp\PHPUnit\AsyncTestCase;
use Amp\Postgres\ConnectionConfig;

class BarTest extends AsyncTestCase {

	public function test() {
		$connection = \Amp\Postgres\pool(ConnectionConfig::fromString("host=localhost port=5432 dbname=rees46_test user=rails password=rails"), 5);

		$result = yield $connection->execute('SELECT 1 AS c');
		if( yield $result->advance() ) {
			$this->assertSame(1, $result->getCurrent()['c']);
		}
	}
	public function test2() {
		$connection = \Amp\Postgres\pool(ConnectionConfig::fromString("host=localhost port=5432 dbname=rees46_test user=rails password=rails"), 5);

		$result = yield $connection->execute('SELECT 1 AS c');
		if( yield $result->advance() ) {
			$this->assertSame(1, $result->getCurrent()['c']);
		}
	}
}

Log:

Testing started at 23:06 ...
PHPUnit 9.5.11 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.0.12
Configuration: /Users/nixx/Projects/rees46-core/phpunit.xml

Time: 00:00.113, Memory: 8.00 MB

OK (2 tests, 2 assertions)

PNixx avatar Dec 27 '21 20:12 PNixx

AsyncTestCase will use a separate event loop per test for isolation purposes, but that makes previous watchers invalid that are still supposed to be active in global state. We've removed swapping the event loop instance in the new major version for that reason.

kelunik avatar Dec 27 '21 23:12 kelunik

Do I need to connect to the DB every time I run a test? This is terrible.

PNixx avatar Dec 28 '21 05:12 PNixx

Currently, that's how it is when using AsyncTestCase, yes.

kelunik avatar Dec 28 '21 16:12 kelunik

The event loop is no longer discarded between each test in AMPHP v3 and therefore in v2.x of this library, so this should no longer be an issue.

That being said, be careful about sharing state between test and that you're doing it intentionally, not accidentally.

trowski avatar Jan 07 '23 15:01 trowski