1
0
mirror of https://github.com/danog/postgres.git synced 2024-11-26 20:15:02 +01:00
postgres/test/AbstractConnectionTest.php

303 lines
9.5 KiB
PHP
Raw Normal View History

<?php
2016-09-14 16:27:39 +02:00
namespace Amp\Postgres\Test;
2017-06-05 06:42:18 +02:00
use Amp\CancellationTokenSource;
2017-05-26 17:47:44 +02:00
use Amp\Loop;
use Amp\Postgres\{
CommandResult, Connection, Listener, Transaction, TransactionError, TupleResult
};
2017-05-26 17:47:44 +02:00
use PHPUnit\Framework\TestCase;
2016-09-14 16:27:39 +02:00
2017-05-26 17:47:44 +02:00
abstract class AbstractConnectionTest extends TestCase {
2016-09-14 16:27:39 +02:00
/** @var \Amp\Postgres\Connection */
protected $connection;
/**
* @return array Start test data for database.
*/
public function getData() {
return [
['amphp', 'org'],
['github', 'com'],
['google', 'com'],
['php', 'net'],
];
}
2017-05-16 06:28:37 +02:00
2016-09-14 16:27:39 +02:00
abstract public function createConnection(string $connectionString): Connection;
abstract public function getConnectCallable(): callable;
2017-05-16 06:28:37 +02:00
2016-09-14 16:27:39 +02:00
public function setUp() {
$this->connection = $this->createConnection('host=localhost user=postgres');
}
2017-05-16 06:28:37 +02:00
2016-09-14 16:27:39 +02:00
public function testQueryWithTupleResult() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
/** @var \Amp\Postgres\TupleResult $result */
$result = yield $this->connection->query("SELECT * FROM test");
$this->assertInstanceOf(TupleResult::class, $result);
$this->assertSame(2, $result->numFields());
2017-05-16 06:28:37 +02:00
2016-09-14 16:27:39 +02:00
$data = $this->getData();
2016-12-30 07:10:43 +01:00
for ($i = 0; yield $result->advance(); ++$i) {
2016-09-14 16:27:39 +02:00
$row = $result->getCurrent();
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
});
2016-09-14 16:27:39 +02:00
}
public function testQueryWithCommandResult() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
/** @var \Amp\Postgres\CommandResult $result */
$result = yield $this->connection->query("INSERT INTO test VALUES ('canon', 'jp')");
$this->assertInstanceOf(CommandResult::class, $result);
$this->assertSame(1, $result->affectedRows());
});
2016-09-14 16:27:39 +02:00
}
/**
* @expectedException \Amp\Postgres\QueryError
*/
public function testQueryWithEmptyQuery() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
/** @var \Amp\Postgres\CommandResult $result */
$result = yield $this->connection->query('');
});
2016-09-14 16:27:39 +02:00
}
/**
* @expectedException \Amp\Postgres\QueryError
*/
public function testQueryWithSyntaxError() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
/** @var \Amp\Postgres\CommandResult $result */
$result = yield $this->connection->query("SELECT & FROM test");
});
2016-09-14 16:27:39 +02:00
}
public function testPrepare() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$query = "SELECT * FROM test WHERE domain=\$1";
/** @var \Amp\Postgres\Statement $statement */
$statement = yield $this->connection->prepare($query);
$this->assertSame($query, $statement->getQuery());
$data = $this->getData()[0];
/** @var \Amp\Postgres\TupleResult $result */
$result = yield $statement->execute($data[0]);
$this->assertInstanceOf(TupleResult::class, $result);
$this->assertSame(2, $result->numFields());
2017-05-16 06:14:02 +02:00
2016-12-30 07:10:43 +01:00
while (yield $result->advance()) {
2016-09-14 16:27:39 +02:00
$row = $result->getCurrent();
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
});
2016-09-14 16:27:39 +02:00
}
public function testExecute() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$data = $this->getData()[0];
/** @var \Amp\Postgres\TupleResult $result */
$result = yield $this->connection->execute("SELECT * FROM test WHERE domain=\$1", $data[0]);
$this->assertInstanceOf(TupleResult::class, $result);
$this->assertSame(2, $result->numFields());
2016-12-30 07:10:43 +01:00
while (yield $result->advance()) {
2016-09-14 16:27:39 +02:00
$row = $result->getCurrent();
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
});
2016-09-14 16:27:39 +02:00
}
/**
* @expectedException \Amp\Postgres\PendingOperationError
2016-09-14 16:27:39 +02:00
*/
public function testSimultaneousQuery() {
Loop::run(function () {
$query1 = $this->connection->query("SELECT 0 as value");
$query2 = $this->connection->query("SELECT 1 as value");
2017-05-16 06:14:02 +02:00
try {
yield $query1;
} catch (\Throwable $exception) {
$this->fail("The first query should be successful");
2016-09-14 16:27:39 +02:00
}
2017-05-16 06:14:02 +02:00
yield $query2;
});
2016-09-14 16:27:39 +02:00
}
public function testTransaction() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$isolation = Transaction::COMMITTED;
/** @var \Amp\Postgres\Transaction $transaction */
$transaction = yield $this->connection->transaction($isolation);
$this->assertInstanceOf(Transaction::class, $transaction);
$data = $this->getData()[0];
$this->assertTrue($transaction->isActive());
$this->assertSame($isolation, $transaction->getIsolationLevel());
yield $transaction->savepoint('test');
$result = yield $transaction->execute("SELECT * FROM test WHERE domain=\$1 FOR UPDATE", $data[0]);
yield $transaction->rollbackTo('test');
yield $transaction->commit();
$this->assertFalse($transaction->isActive());
try {
$result = yield $transaction->execute("SELECT * FROM test");
$this->fail('Query should fail after transaction commit');
} catch (TransactionError $exception) {
// Exception expected.
}
});
2016-09-14 16:27:39 +02:00
}
2017-05-16 06:14:02 +02:00
public function testListen() {
Loop::run(function () {
$channel = "test";
/** @var \Amp\Postgres\Listener $listener */
$listener = yield $this->connection->listen($channel);
$this->assertInstanceOf(Listener::class, $listener);
yield $this->connection->query(\sprintf("NOTIFY %s, '%s'", $channel, '0'));
yield $this->connection->query(\sprintf("NOTIFY %s, '%s'", $channel, '1'));
$count = 0;
Loop::defer(function () use (&$count, $listener) {
$listener->unlisten();
$this->assertSame(2, $count);
});
while (yield $listener->advance()) {
$this->assertSame($listener->getCurrent()->payload, (string) $count++);
}
});
}
/**
* @depends testListen
*/
public function testNotify() {
Loop::run(function () {
$channel = "test";
/** @var \Amp\Postgres\Listener $listener */
$listener = yield $this->connection->listen($channel);
yield $this->connection->notify($channel, '0');
yield $this->connection->notify($channel, '1');
$count = 0;
Loop::defer(function () use (&$count, $listener) {
$listener->unlisten();
$this->assertSame(2, $count);
});
while (yield $listener->advance()) {
$this->assertSame($listener->getCurrent()->payload, (string) $count++);
}
});
}
/**
* @depends testListen
* @expectedException \Amp\Postgres\QueryError
* @expectedExceptionMessage Already listening on channel
*/
public function testListenOnSameChannel() {
Loop::run(function () {
$channel = "test";
$listener = yield $this->connection->listen($channel);
$listener = yield $this->connection->listen($channel);
});
}
2016-09-14 16:27:39 +02:00
public function testConnect() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$connect = $this->getConnectCallable();
$connection = yield $connect('host=localhost user=postgres');
$this->assertInstanceOf(Connection::class, $connection);
});
2016-09-14 16:27:39 +02:00
}
2017-05-16 06:14:02 +02:00
2016-09-14 16:27:39 +02:00
/**
* @expectedException \Amp\Postgres\FailureException
*/
public function testConnectInvalidUser() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$connect = $this->getConnectCallable();
2017-06-05 06:42:18 +02:00
$connection = yield $connect('host=localhost user=invalid');
});
2016-09-14 16:27:39 +02:00
}
2017-05-16 06:14:02 +02:00
2016-09-14 16:27:39 +02:00
/**
* @expectedException \Amp\Postgres\FailureException
*/
public function testConnectInvalidConnectionString() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$connect = $this->getConnectCallable();
2017-06-05 06:42:18 +02:00
$connection = yield $connect('invalid connection string');
});
2016-09-14 16:27:39 +02:00
}
2017-05-16 06:14:02 +02:00
2016-09-14 16:27:39 +02:00
/**
* @expectedException \Amp\Postgres\FailureException
*/
public function testConnectInvalidHost() {
Loop::run(function () {
2016-09-14 16:27:39 +02:00
$connect = $this->getConnectCallable();
2017-06-05 06:42:18 +02:00
$connection = yield $connect('hostaddr=invalid.host user=postgres');
});
}
/**
* @expectedException \Amp\CancelledException
*/
public function testConnectCancellationBeforeConnect() {
Loop::run(function () {
$connect = $this->getConnectCallable();
$source = new CancellationTokenSource;
$token = $source->getToken();
$source->cancel();
$connection = yield $connect('host=localhost user=postgres', $token);
});
}
public function testConnectCancellationAfterConnect() {
Loop::run(function () {
$connect = $this->getConnectCallable();
$source = new CancellationTokenSource;
$token = $source->getToken();
$connection = yield $connect('host=localhost user=postgres', $token);
$this->assertInstanceOf(Connection::class, $connection);
$source->cancel();
});
2016-09-14 16:27:39 +02:00
}
}