1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Provide an "isolated" database connection for testing

Summary:
This provides a new connection which doesn't connect to
anything, so effects can be isolated to the current process (for
unit testing).

Test Plan:
Ran unit tests.

Reviewed By: aran
Reviewers: aran, tuomaspelkonen, jungejason
CC: aran, epriestley
Differential Revision: 193
This commit is contained in:
epriestley 2011-04-30 10:11:41 -07:00
parent 0e06cd85b7
commit 7387cd63ac
7 changed files with 232 additions and 0 deletions

View file

@ -39,6 +39,8 @@ phutil_register_library_map(array(
'AphrontFormView' => 'view/form/base', 'AphrontFormView' => 'view/form/base',
'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist', 'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist',
'AphrontHeadsupActionView' => 'view/layout/headsup/action', 'AphrontHeadsupActionView' => 'view/layout/headsup/action',
'AphrontIsolatedDatabaseConnection' => 'storage/connection/isolated',
'AphrontIsolatedDatabaseConnectionTestCase' => 'storage/connection/isolated/__tests__',
'AphrontListFilterView' => 'view/layout/listfilter', 'AphrontListFilterView' => 'view/layout/listfilter',
'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql', 'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql',
'AphrontNullView' => 'view/null', 'AphrontNullView' => 'view/null',
@ -416,6 +418,7 @@ phutil_register_library_map(array(
'PhabricatorStandardPageView' => 'view/page/standard', 'PhabricatorStandardPageView' => 'view/page/standard',
'PhabricatorStatusController' => 'applications/status/base', 'PhabricatorStatusController' => 'applications/status/base',
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster', 'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster',
'PhabricatorTestCase' => 'infrastructure/testing/testcase',
'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor', 'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor',
'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/base', 'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/base',
'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/event', 'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/event',
@ -504,6 +507,8 @@ phutil_register_library_map(array(
'AphrontFormView' => 'AphrontView', 'AphrontFormView' => 'AphrontView',
'AphrontHeadsupActionListView' => 'AphrontView', 'AphrontHeadsupActionListView' => 'AphrontView',
'AphrontHeadsupActionView' => 'AphrontView', 'AphrontHeadsupActionView' => 'AphrontView',
'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase',
'AphrontListFilterView' => 'AphrontView', 'AphrontListFilterView' => 'AphrontView',
'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontNullView' => 'AphrontView', 'AphrontNullView' => 'AphrontView',
@ -795,6 +800,7 @@ phutil_register_library_map(array(
'PhabricatorStandardPageView' => 'AphrontPageView', 'PhabricatorStandardPageView' => 'AphrontPageView',
'PhabricatorStatusController' => 'PhabricatorController', 'PhabricatorStatusController' => 'PhabricatorController',
'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon', 'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO', 'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',

View file

@ -0,0 +1,26 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class PhabricatorTestCase extends ArcanistPhutilTestCase {
protected function willRunTests() {
$root = dirname(phutil_get_library_root('phabricator'));
require_once $root.'/scripts/__init_env__.php';
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('arcanist', 'unit/engine/phutil/testcase');
phutil_require_module('phutil', 'moduleutils');
phutil_require_source('PhabricatorTestCase.php');

View file

@ -0,0 +1,90 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @group storage
*/
class AphrontIsolatedDatabaseConnection extends AphrontDatabaseConnection {
private $configuration;
private static $nextInsertID;
private $insertID;
public function __construct(array $configuration) {
$this->configuration = $configuration;
if (self::$nextInsertID === null) {
// Generate test IDs into a distant ID space to reduce the risk of
// collisions and make them distinctive.
self::$nextInsertID = 55555000000 + mt_rand(0, 1000);
}
}
public function escapeString($string) {
return '<S>';
}
public function escapeColumnName($name) {
return '<C>';
}
public function escapeMultilineComment($comment) {
return '<K>';
}
public function escapeStringForLikeClause($value) {
return '<L>';
}
private function getConfiguration($key, $default = null) {
return idx($this->configuration, $key, $default);
}
public function getInsertID() {
return $this->insertID;
}
public function getAffectedRows() {
return $this->affectedRows;
}
public function getTransactionKey() {
return 'xaction'; // TODO, probably need to stub this better.
}
public function selectAllResults() {
return $this->allResults;
}
public function executeRawQuery($raw_query) {
// NOTE: This method is intentionally simplified for now, since we're only
// using it to stub out inserts/updates. In the future it will probably need
// to grow more powerful.
$this->allResults = array();
// NOTE: We jitter the insert IDs to keep tests honest; a test should cover
// the relationship between objects, not their exact insertion order. This
// guarantees that IDs are unique but makes it impossible to hard-code tests
// against this specific implementation detail.
$this->insertID = (self::$nextInsertID += mt_rand(1, 10));
$this->affectedRows = 1;
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'storage/connection/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('AphrontIsolatedDatabaseConnection.php');

View file

@ -0,0 +1,65 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class AphrontIsolatedDatabaseConnectionTestCase
extends PhabricatorTestCase {
public function testIsolation() {
$conn = $this->newIsolatedConnection();
$test_phid = 'PHID-TEST-'.sha1(mt_rand());
queryfx(
$conn,
'INSERT INTO phabricator_phid.phid (phid) VALUES (%s)',
$test_phid);
try {
$real_phid = id(new PhabricatorPHID())->loadOneWhere(
'phid = %s',
$test_phid);
$this->assertEqual(
null,
$real_phid,
'Expect fake PHID to exist only in isolation.');
} catch (AphrontQueryConnectionException $ex) {
// If we can't connect to the database, conclude that the isolated
// connection actually is isolated. Philosophically, this perhaps allows
// us to claim this test does not depend on the database?
}
}
public function testInsertGeneratesID() {
$conn = $this->newIsolatedConnection();
queryfx($conn, 'INSERT');
$id1 = $conn->getInsertID();
queryfx($conn, 'INSERT');
$id2 = $conn->getInsertID();
$this->assertEqual(true, (bool)$id1, 'ID1 exists.');
$this->assertEqual(true, (bool)$id2, 'ID2 exists.');
$this->assertEqual(true, $id1 != $id2, 'IDs are distinct.');
}
private function newIsolatedConnection() {
$config = array();
return new AphrontIsolatedDatabaseConnection($config);
}
}

View file

@ -0,0 +1,17 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/phid/storage/phid');
phutil_require_module('phabricator', 'infrastructure/testing/testcase');
phutil_require_module('phabricator', 'storage/connection/isolated');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phutil', 'utils');
phutil_require_source('AphrontIsolatedDatabaseConnectionTestCase.php');