Added tests for the Store (MySQL and PostgreSQL).

This commit is contained in:
Dmitry Khomutov 2018-03-01 19:36:28 +07:00
parent 9fc73577ca
commit 42a8316479
No known key found for this signature in database
GPG key ID: EC19426474B37AAC
14 changed files with 591 additions and 182 deletions

View file

@ -2,8 +2,6 @@
namespace b8; namespace b8;
use b8\Exception\HttpException;
abstract class Store abstract class Store
{ {
/** /**
@ -25,19 +23,25 @@ abstract class Store
* @param string $key * @param string $key
* @param string $useConnection * @param string $useConnection
* *
* @return Model * @return Model|null
*/ */
abstract public function getByPrimaryKey($key, $useConnection = 'read'); abstract public function getByPrimaryKey($key, $useConnection = 'read');
/**
* @throws \RuntimeException
*/
public function __construct()
{
if (empty($this->primaryKey)) {
throw new \RuntimeException('Save not implemented for this store.');
}
}
/** /**
* @param array $where * @param array $where
* @param integer $limit * @param integer $limit
* @param integer $offset * @param integer $offset
* @param array $joins
* @param array $order * @param array $order
* @param array $manualJoins
* @param string $group
* @param array $manualWheres
* @param string $whereType * @param string $whereType
* *
* @return array * @return array
@ -46,11 +50,7 @@ abstract class Store
$where = [], $where = [],
$limit = 25, $limit = 25,
$offset = 0, $offset = 0,
$joins = [],
$order = [], $order = [],
$manualJoins = [],
$group = null,
$manualWheres = [],
$whereType = 'AND' $whereType = 'AND'
) { ) {
$query = 'SELECT * FROM {{' . $this->tableName . '}}'; $query = 'SELECT * FROM {{' . $this->tableName . '}}';
@ -64,129 +64,21 @@ abstract class Store
if (!is_array($value)) { if (!is_array($value)) {
$params[] = $value; $params[] = $value;
$wheres[] = $key . ' = ?'; $wheres[] = $key . ' = ?';
} else {
if (isset($value['operator'])) {
if (is_array($value['value'])) {
if ($value['operator'] == 'between') {
$params[] = $value['value'][0];
$params[] = $value['value'][1];
$wheres[] = $key . ' BETWEEN ? AND ?';
} elseif ($value['operator'] == 'IN') {
$in = [];
foreach ($value['value'] as $item) {
$params[] = $item;
$in[] = '?';
}
$wheres[] = $key . ' IN (' . implode(', ', $in) . ') ';
} else {
$ors = [];
foreach ($value['value'] as $item) {
if ($item == 'null') {
switch ($value['operator']) {
case '!=':
$ors[] = $key . ' IS NOT NULL';
break;
case '==':
default:
$ors[] = $key . ' IS NULL';
break;
}
} else {
$params[] = $item;
$ors[] = $key . ' ' . $value['operator'] . ' ?';
}
}
$wheres[] = '(' . implode(' OR ', $ors) . ')';
}
} else {
if ($value['operator'] == 'like') {
$params[] = '%' . $value['value'] . '%';
$wheres[] = $key . ' ' . $value['operator'] . ' ?';
} else {
if ($value['value'] === 'null') {
switch ($value['operator']) {
case '!=':
$wheres[] = $key . ' IS NOT NULL';
break;
case '==':
default:
$wheres[] = $key . ' IS NULL';
break;
}
} else {
$params[] = $value['value'];
$wheres[] = $key . ' ' . $value['operator'] . ' ?';
}
}
}
} else {
$wheres[] = $key . ' IN (' . implode(', ', array_map([Database::getConnection('read'), 'quote'], $value)) . ')';
}
} }
} }
if (count($joins)) {
foreach ($joins as $table => $join) {
$query .= ' LEFT JOIN {{' . $table . '}} AS ' . $join['alias'] . ' ON ' . $join['on'] . ' ';
$countQuery .= ' LEFT JOIN {{' . $table . '}} AS ' . $join['alias'] . ' ON ' . $join['on'] . ' ';
}
}
if (count($manualJoins)) {
foreach ($manualJoins as $join) {
$query .= ' ' . $join . ' ';
$countQuery .= ' ' . $join . ' ';
}
}
$hasWhere = false;
if (count($wheres)) { if (count($wheres)) {
$hasWhere = true;
$query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')'; $query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
$countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')'; $countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
} }
if (count($manualWheres)) {
foreach ($manualWheres as $where) {
if (!$hasWhere) {
$hasWhere = true;
$query .= ' WHERE ';
$countQuery .= ' WHERE ';
} else {
$query .= ' ' . $where['type'] . ' ';
$countQuery .= ' ' . $where['type'] . ' ';
}
$query .= ' ' . $where['query'];
$countQuery .= ' ' . $where['query'];
if (isset($where['params'])) {
foreach ($where['params'] as $param) {
$params[] = $param;
}
}
}
}
if (!is_null($group)) {
$query .= ' GROUP BY ' . $group . ' ';
}
if (count($order)) { if (count($order)) {
$orders = []; $orders = [];
if (is_string($order) && $order == 'rand') { foreach ($order as $key => $value) {
$query .= ' ORDER BY RAND() '; $orders[] = $this->fieldCheck($key) . ' ' . $value;
} else {
foreach ($order as $key => $value) {
$orders[] = $this->fieldCheck($key) . ' ' . $value;
}
$query .= ' ORDER BY ' . implode(', ', $orders);
} }
$query .= ' ORDER BY ' . implode(', ', $orders);
} }
if ($limit) { if ($limit) {
@ -197,47 +89,36 @@ abstract class Store
$query .= ' OFFSET ' . $offset; $query .= ' OFFSET ' . $offset;
} }
try { $stmt = Database::getConnection('read')->prepareCommon($countQuery);
$stmt = Database::getConnection('read')->prepareCommon($countQuery); $stmt->execute($params);
$stmt->execute($params); $res = $stmt->fetch(\PDO::FETCH_ASSOC);
$res = $stmt->fetch(\PDO::FETCH_ASSOC); $count = (int)$res['count'];
$count = (int)$res['count'];
} catch (\PDOException $ex) { $stmt = Database::getConnection('read')->prepareCommon($query);
$count = 0; $stmt->execute($params);
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$rtn = [];
foreach ($res as $data) {
$rtn[] = new $this->modelName($data);
} }
try { return ['items' => $rtn, 'count' => $count];
$stmt = Database::getConnection('read')->prepareCommon($query);
$stmt->execute($params);
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$rtn = [];
foreach ($res as $data) {
$rtn[] = new $this->modelName($data);
}
return ['items' => $rtn, 'count' => $count];
} catch (\PDOException $ex) {
throw $ex;
}
} }
/** /**
* @param Model $obj * @param Model $obj
* @param boolean $saveAllColumns * @param boolean $saveAllColumns
* *
* @throws HttpException\BadRequestException * @throws \RuntimeException
* @throws \InvalidArgumentException
* *
* @return Model|null * @return Model|null
*/ */
public function save(Model $obj, $saveAllColumns = false) public function save(Model $obj, $saveAllColumns = false)
{ {
if (!isset($this->primaryKey)) {
throw new HttpException\BadRequestException('Save not implemented for this store.');
}
if (!($obj instanceof $this->modelName)) { if (!($obj instanceof $this->modelName)) {
throw new HttpException\BadRequestException(get_class($obj) . ' is an invalid model type for this store.'); throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
} }
$data = $obj->getDataArray(); $data = $obj->getDataArray();
@ -315,10 +196,7 @@ abstract class Store
$q = Database::getConnection('write')->prepareCommon($qs); $q = Database::getConnection('write')->prepareCommon($qs);
if ($q->execute($qParams)) { if ($q->execute($qParams)) {
$id = !empty($data[$this->primaryKey]) $id = Database::getConnection('write')->lastInsertIdExtended($obj->getTableName());
? $data[$this->primaryKey]
: Database::getConnection('write')->lastInsertIdExtended($obj->getTableName());
$rtn = $this->getByPrimaryKey($id, 'write'); $rtn = $this->getByPrimaryKey($id, 'write');
} }
} }
@ -329,18 +207,15 @@ abstract class Store
/** /**
* @param Model $obj * @param Model $obj
* *
* @throws HttpException\BadRequestException * @throws \RuntimeException
* @throws \InvalidArgumentException
* *
* @return boolean * @return boolean
*/ */
public function delete(Model $obj) public function delete(Model $obj)
{ {
if (!isset($this->primaryKey)) {
throw new HttpException\BadRequestException('Delete not implemented for this store.');
}
if (!($obj instanceof $this->modelName)) { if (!($obj instanceof $this->modelName)) {
throw new HttpException\BadRequestException(get_class($obj) . ' is an invalid model type for this store.'); throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
} }
$data = $obj->getDataArray(); $data = $obj->getDataArray();
@ -355,14 +230,14 @@ abstract class Store
/** /**
* @param string $field * @param string $field
* *
* @throws HttpException * @throws \InvalidArgumentException
* *
* @return string * @return string
*/ */
protected function fieldCheck($field) protected function fieldCheck($field)
{ {
if (empty($field)) { if (empty($field)) {
throw new HttpException('You cannot have an empty field name.'); throw new \InvalidArgumentException('You cannot have an empty field name.');
} }
if (strpos($field, '.') === false) { if (strpos($field, '.') === false) {

View file

@ -13,6 +13,7 @@ class Factory
/** /**
* A collection of the stores currently loaded by the factory. * A collection of the stores currently loaded by the factory.
*
* @var \b8\Store[] * @var \b8\Store[]
*/ */
protected $loadedStores = []; protected $loadedStores = [];
@ -30,7 +31,8 @@ class Factory
} }
/** /**
* @param $storeName string Store name (should match a model name). * @param string $storeName Store name (should match a model name).
* @param string $namespace
* *
* @return \b8\Store * @return \b8\Store
*/ */
@ -45,17 +47,20 @@ class Factory
} }
/** /**
* @param $store * @param string $store
* @param string $namespace
* *
* @return \b8\Store; * @return \b8\Store;
*/ */
public function loadStore($store, $namespace = null) public function loadStore($store, $namespace = null)
{ {
if (!isset($this->loadedStores[$store])) { if (!isset($this->loadedStores[$store])) {
$namespace = is_null($namespace) ? Config::getInstance()->get('b8.app.namespace') : $namespace; $namespace = is_null($namespace)
$class = $namespace . '\\Store\\' . $store . 'Store'; ? Config::getInstance()->get('b8.app.namespace')
$obj = new $class(); : $namespace;
$class = $namespace . '\\Store\\' . $store . 'Store';
$obj = new $class();
$this->loadedStores[$store] = $obj; $this->loadedStores[$store] = $obj;
} }

View file

@ -129,7 +129,7 @@ class Application extends b8\Application
{ {
$groups = []; $groups = [];
$groupStore = b8\Store\Factory::getStore('ProjectGroup'); $groupStore = b8\Store\Factory::getStore('ProjectGroup');
$groupList = $groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); $groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) { foreach ($groupList['items'] as $group) {
$thisGroup = ['title' => $group->getTitle()]; $thisGroup = ['title' => $group->getTitle()];

View file

@ -225,7 +225,7 @@ class BuildStatusController extends Controller
{ {
$criteria = ['project_id' => $projectId]; $criteria = ['project_id' => $projectId];
$order = ['id' => 'DESC']; $order = ['id' => 'DESC'];
$builds = $this->buildStore->getWhere($criteria, 10, 0, [], $order); $builds = $this->buildStore->getWhere($criteria, 10, 0, $order);
foreach ($builds['items'] as &$build) { foreach ($builds['items'] as &$build) {
$build = BuildFactory::getBuild($build); $build = BuildFactory::getBuild($build);

View file

@ -37,7 +37,7 @@ class GroupController extends Controller
$this->requireAdmin(); $this->requireAdmin();
$groups = []; $groups = [];
$groupList = $this->groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); $groupList = $this->groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) { foreach ($groupList['items'] as $group) {
$thisGroup = [ $thisGroup = [

View file

@ -273,7 +273,7 @@ class ProjectController extends PHPCensor\Controller
} }
$order = ['id' => 'DESC']; $order = ['id' => 'DESC'];
$builds = $this->buildStore->getWhere($criteria, $perPage, $start, [], $order); $builds = $this->buildStore->getWhere($criteria, $perPage, $start, $order);
$view = new View('Project/ajax-builds'); $view = new View('Project/ajax-builds');
foreach ($builds['items'] as &$build) { foreach ($builds['items'] as &$build) {
@ -496,7 +496,7 @@ class ProjectController extends PHPCensor\Controller
$groups = []; $groups = [];
$groupStore = b8\Store\Factory::getStore('ProjectGroup'); $groupStore = b8\Store\Factory::getStore('ProjectGroup');
$groupList = $groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); $groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) { foreach ($groupList['items'] as $group) {
$groups[$group->getId()] = $group->getTitle(); $groups[$group->getId()] = $group->getTitle();

View file

@ -42,7 +42,7 @@ class UserController extends Controller
*/ */
public function index() public function index()
{ {
$users = $this->userStore->getWhere([], 1000, 0, [], ['email' => 'ASC']); $users = $this->userStore->getWhere([], 1000, 0, ['email' => 'ASC']);
$this->view->users = $users; $this->view->users = $users;
$this->layout->title = Lang::get('manage_users'); $this->layout->title = Lang::get('manage_users');

View file

@ -76,7 +76,6 @@ class WidgetAllProjectsController extends Controller
['project_id' => $project->getId()], ['project_id' => $project->getId()],
1, 1,
0, 0,
[],
['id' => 'DESC'] ['id' => 'DESC']
); );
$counts[$project->getId()] = $count['count']; $counts[$project->getId()] = $count['count'];
@ -107,7 +106,7 @@ class WidgetAllProjectsController extends Controller
protected function getGroupInfo() protected function getGroupInfo()
{ {
$rtn = []; $rtn = [];
$groups = $this->groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); $groups = $this->groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groups['items'] as $group) { foreach ($groups['items'] as $group) {
$thisGroup = ['title' => $group->getTitle()]; $thisGroup = ['title' => $group->getTitle()];
@ -133,7 +132,6 @@ class WidgetAllProjectsController extends Controller
['project_id' => $projectId], ['project_id' => $projectId],
1, 1,
0, 0,
[],
['id' => 'DESC'] ['id' => 'DESC']
); );
$counts = $count['count']; $counts = $count['count'];

View file

@ -512,7 +512,7 @@ class Project extends Model
} }
$order = ['id' => 'DESC']; $order = ['id' => 'DESC'];
$builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 0, [], $order); $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 0, $order);
if (is_array($builds['items']) && count($builds['items'])) { if (is_array($builds['items']) && count($builds['items'])) {
$latest = array_shift($builds['items']); $latest = array_shift($builds['items']);
@ -536,7 +536,7 @@ class Project extends Model
{ {
$criteria = ['branch' => $branch, 'project_id' => $this->getId()]; $criteria = ['branch' => $branch, 'project_id' => $this->getId()];
$order = ['id' => 'DESC']; $order = ['id' => 'DESC'];
$builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 1, [], $order); $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 1, $order);
if (is_array($builds['items']) && count($builds['items'])) { if (is_array($builds['items']) && count($builds['items'])) {
$previous = array_shift($builds['items']); $previous = array_shift($builds['items']);

View file

@ -33,7 +33,7 @@ class ProjectStore extends Store
* @param integer $key * @param integer $key
* @param string $useConnection * @param string $useConnection
* *
* @return null|Project * @return Project|null
*/ */
public function getByPrimaryKey($key, $useConnection = 'read') public function getByPrimaryKey($key, $useConnection = 'read')
{ {
@ -46,7 +46,7 @@ class ProjectStore extends Store
* @param integer $id * @param integer $id
* @param string $useConnection * @param string $useConnection
* *
* @return null|Project * @return Project|null
* *
* @throws HttpException * @throws HttpException
*/ */

View file

@ -39,7 +39,7 @@ class DatabaseMysqlTest extends \PHPUnit_Extensions_Database_TestCase
`branch` varchar(250) NOT NULL DEFAULT \'master\', `branch` varchar(250) NOT NULL DEFAULT \'master\',
`createDate` datetime, `createDate` datetime,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8
'); ');
} catch (\PDOException $ex) { } catch (\PDOException $ex) {
$this->connection = null; $this->connection = null;

View file

@ -39,7 +39,7 @@ class DatabasePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
"branch" character varying(250) NOT NULL DEFAULT \'master\', "branch" character varying(250) NOT NULL DEFAULT \'master\',
"createDate" timestamp without time zone, "createDate" timestamp without time zone,
PRIMARY KEY ("id") PRIMARY KEY ("id")
); )
'); ');
} catch (\PDOException $ex) { } catch (\PDOException $ex) {
$this->connection = null; $this->connection = null;

View file

@ -0,0 +1,268 @@
<?php
namespace Tests\b8;
use b8\Config;
use b8\Database;
use b8\Store;
use b8\Store\Factory;
use PHPCensor\Model\Project;
use PHPCensor\Model\ProjectGroup;
class WrongStore extends Store
{
protected $tableName = 'project_group';
protected $modelName = '\PHPCensor\Model\ProjectGroup';
public function getByPrimaryKey($key, $useConnection = 'read')
{
return null;
}
}
class StoreMysqlTest extends \PHPUnit_Extensions_Database_TestCase
{
/**
* @var \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection|null
*/
protected $connection = null;
/**
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
if (extension_loaded('mysqli')) {
if (null === $this->connection) {
try {
$pdo = new \PDO(
'mysql:host=localhost;dbname=' . MYSQL_DBNAME,
MYSQL_USER,
MYSQL_PASSWORD
);
$this->connection = $this->createDefaultDBConnection($pdo, MYSQL_DBNAME);
$this->connection->getConnection()->query('
CREATE TABLE IF NOT EXISTS `project_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`create_date` datetime,
`user_id` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
');
} catch (\PDOException $ex) {
$this->connection = null;
}
}
} else {
$this->connection = null;
}
}
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
if (null === $this->connection) {
$this->markTestSkipped('Test skipped because MySQL database/user/extension doesn`t exist.');
}
return $this->connection;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
return $this->createArrayDataSet([
'project_group' => [[
'id' => 1,
'title' => 'group 1',
'create_date' => null,
'user_id' => 0,
], [
'id' => 2,
'title' => 'group 2',
'create_date' => null,
'user_id' => 0,
], [
'id' => 3,
'title' => 'group 3',
'create_date' => null,
'user_id' => 1,
], [
'id' => 4,
'title' => 'group 4',
'create_date' => null,
'user_id' => 1,
], [
'id' => 5,
'title' => 'group 5',
'create_date' => '2018-01-01 01:01:00',
'user_id' => 2,
], [
'id' => 6,
'title' => 'group 6',
'create_date' => '2018-02-01 01:01:00',
'user_id' => 3,
], [
'id' => 7,
'title' => 'group 7',
'create_date' => '2018-03-01 01:01:00',
'user_id' => 4,
]],
]);
}
protected function setUp()
{
parent::setUp();
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::MYSQL_TYPE,
'name' => MYSQL_DBNAME,
'username' => MYSQL_USER,
'password' => MYSQL_PASSWORD,
],
],
]);
Database::reset();
}
/**
* @expectedException \RuntimeException
*/
public function testConstruct()
{
$store = new WrongStore();
}
public function testGetWhere()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']);
self::assertEquals(7, $data['count']);
self::assertEquals(3, count($data['items']));
self::assertEquals(6, $data['items'][0]->getId());
self::assertEquals(5, $data['items'][1]->getId());
self::assertEquals(4, $data['items'][2]->getId());
$data = $testStore->getWhere(['project_group.user_id' => 0], 100, 0, ['id' => 'ASC']);
self::assertEquals(2, $data['count']);
self::assertEquals(2, count($data['items']));
self::assertEquals(1, $data['items'][0]->getId());
self::assertEquals(2, $data['items'][1]->getId());
try {
$data = $testStore->getWhere(['' => 0], 100, 0, ['id' => 'ASC']);
} catch (\InvalidArgumentException $e) {
self::assertEquals('You cannot have an empty field name.', $e->getMessage());
}
try {
$data = $testStore->getWhere([], '; SELECT', 0, ['id' => 'ASC']);
} catch (\PDOException $e) {
self::assertInstanceOf('\PDOException', $e);
}
}
public function testSaveByInsert()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$model = new ProjectGroup();
$model->setTitle('group 8');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(8);
self::assertEquals(8, $newModel->getId());
self::assertEquals('group 8', $newModel->getTitle());
}
public function testSaveByUpdate()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$model = $testStore->getByPrimaryKey(7);
$model->setTitle('group 100');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(7);
self::assertEquals(7, $newModel->getId());
self::assertEquals('group 100', $newModel->getTitle());
// Without changes
$model = $testStore->getByPrimaryKey(6);
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(6);
self::assertEquals(6, $newModel->getId());
self::assertEquals('group 6', $newModel->getTitle());
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->save($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
public function testDelete()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$model = $testStore->getByPrimaryKey(5);
$testStore->delete($model);
$newModel = $testStore->getByPrimaryKey(5);
self::assertEquals(null, $newModel);
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->delete($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
}

View file

@ -0,0 +1,263 @@
<?php
namespace Tests\b8;
use b8\Config;
use b8\Database;
use b8\Store\Factory;
use PHPCensor\Model\Project;
use PHPCensor\Model\ProjectGroup;
class StorePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
{
/**
* @var \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection|null
*/
protected $connection = null;
/**
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
if (extension_loaded('pgsql')) {
if (null === $this->connection) {
try {
$pdo = new \PDO(
'pgsql:host=localhost;dbname=' . POSTGRESQL_DBNAME,
POSTGRESQL_USER,
POSTGRESQL_PASSWORD
);
$this->connection = $this->createDefaultDBConnection($pdo, POSTGRESQL_DBNAME);
$this->connection->getConnection()->query('
CREATE TABLE IF NOT EXISTS "project_group" (
"id" SERIAL,
"title" character varying(100) NOT NULL,
"create_date" timestamp without time zone,
"user_id" integer NOT NULL DEFAULT 0,
PRIMARY KEY ("id")
)
');
} catch (\PDOException $ex) {
$this->connection = null;
}
}
} else {
$this->connection = null;
}
}
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
if (null === $this->connection) {
$this->markTestSkipped('Test skipped because PostgreSQL database/user/extension doesn`t exist.');
}
return $this->connection;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
return $this->createArrayDataSet([
'project_group' => [[
'id' => 1,
'title' => 'group 1',
'create_date' => null,
'user_id' => 0,
], [
'id' => 2,
'title' => 'group 2',
'create_date' => null,
'user_id' => 0,
], [
'id' => 3,
'title' => 'group 3',
'create_date' => null,
'user_id' => 1,
], [
'id' => 4,
'title' => 'group 4',
'create_date' => null,
'user_id' => 1,
], [
'id' => 5,
'title' => 'group 5',
'create_date' => '2018-01-01 01:01:00',
'user_id' => 2,
], [
'id' => 6,
'title' => 'group 6',
'create_date' => '2018-02-01 01:01:00',
'user_id' => 3,
], [
'id' => 7,
'title' => 'group 7',
'create_date' => '2018-03-01 01:01:00',
'user_id' => 4,
]],
]);
}
protected function setUp()
{
parent::setUp();
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::POSTGRESQL_TYPE,
'name' => POSTGRESQL_DBNAME,
'username' => POSTGRESQL_USER,
'password' => POSTGRESQL_PASSWORD,
],
],
]);
Database::reset();
}
/**
* @expectedException \RuntimeException
*/
public function testConstruct()
{
$store = new WrongStore();
}
public function testGetWhere()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']);
self::assertEquals(7, $data['count']);
self::assertEquals(3, count($data['items']));
self::assertEquals(6, $data['items'][0]->getId());
self::assertEquals(5, $data['items'][1]->getId());
self::assertEquals(4, $data['items'][2]->getId());
$data = $testStore->getWhere(['project_group.user_id' => 0], 100, 0, ['id' => 'ASC']);
self::assertEquals(2, $data['count']);
self::assertEquals(2, count($data['items']));
self::assertEquals(1, $data['items'][0]->getId());
self::assertEquals(2, $data['items'][1]->getId());
try {
$data = $testStore->getWhere(['' => 0], 100, 0, ['id' => 'ASC']);
} catch (\InvalidArgumentException $e) {
self::assertEquals('You cannot have an empty field name.', $e->getMessage());
}
try {
$data = $testStore->getWhere([], '; SELECT', 0, ['id' => 'ASC']);
} catch (\PDOException $e) {
self::assertInstanceOf('\PDOException', $e);
}
}
public function testSaveByInsert()
{
$this->connection->getConnection()->query('
ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8;
');
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$model = new ProjectGroup();
$model->setTitle('group 8');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(8);
self::assertEquals(8, $newModel->getId());
self::assertEquals('group 8', $newModel->getTitle());
}
public function testSaveByUpdate()
{
$this->connection->getConnection()->query('
ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8;
');
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$model = $testStore->getByPrimaryKey(7);
$model->setTitle('group 100');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(7);
self::assertEquals(7, $newModel->getId());
self::assertEquals('group 100', $newModel->getTitle());
// Without changes
$model = $testStore->getByPrimaryKey(6);
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(6);
self::assertEquals(6, $newModel->getId());
self::assertEquals('group 6', $newModel->getTitle());
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->save($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
public function testDelete()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$model = $testStore->getByPrimaryKey(5);
$testStore->delete($model);
$newModel = $testStore->getByPrimaryKey(5);
self::assertEquals(null, $newModel);
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->delete($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
}