diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index ca63615948..dc6b644d4a 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2862,6 +2862,7 @@ phutil_register_library_map(array( 'PhabricatorProjectMembersPolicyRule' => 'applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php', 'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php', 'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php', + 'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php', 'PhabricatorProjectNoProjectsDatasource' => 'applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php', 'PhabricatorProjectObjectHasProjectEdgeType' => 'applications/project/edge/PhabricatorProjectObjectHasProjectEdgeType.php', 'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php', @@ -7199,6 +7200,7 @@ phutil_register_library_map(array( 'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController', 'PhabricatorProjectMoveController' => 'PhabricatorProjectController', + 'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorProjectNoProjectsDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectObjectHasProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', diff --git a/src/applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php b/src/applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php index 2620216d9f..737db1aef8 100644 --- a/src/applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php +++ b/src/applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php @@ -27,13 +27,10 @@ final class PhabricatorDifferentialRevisionTestDataGenerator ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) ->setNewValue($diff->getPHID()); - $content_source = PhabricatorContentSource::newForSource( - PhabricatorContentSource::SOURCE_LIPSUM, - array()); id(new DifferentialTransactionEditor()) ->setActor($author) - ->setContentSource($content_source) + ->setContentSource($this->getLipsumContentSource()) ->applyTransactions($revision, $xactions); return $revision; diff --git a/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php b/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php index 695e3e6e8f..4e8a9b5985 100644 --- a/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php +++ b/src/applications/lipsum/generator/PhabricatorTestDataGenerator.php @@ -2,9 +2,81 @@ abstract class PhabricatorTestDataGenerator extends Phobject { + private $viewer; + abstract public function getGeneratorName(); abstract public function generateObject(); + final public function setViewer(PhabricatorUser $viewer) { + $this->viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + protected function loadRandomPHID($table) { + $conn_r = $table->establishConnection('r'); + + $row = queryfx_one( + $conn_r, + 'SELECT phid FROM %T ORDER BY RAND() LIMIT 1', + $table->getTableName()); + + if (!$row) { + return null; + } + + return $row['phid']; + } + + protected function loadRandomUser() { + $viewer = $this->getViewer(); + + $user_phid = $this->loadRandomPHID(new PhabricatorUser()); + + $user = null; + if ($user_phid) { + $user = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($user_phid)) + ->executeOne(); + } + + if (!$user) { + throw new Exception( + pht( + 'Failed to load a random user. You may need to generate more '. + 'test users first.')); + } + + return $user; + } + + protected function getLipsumContentSource() { + return PhabricatorContentSource::newForSource( + PhabricatorContentSource::SOURCE_LIPSUM, + array()); + } + + /** + * Roll `n` dice with `d` sides each, then add `bonus` and return the sum. + */ + protected function roll($n, $d, $bonus = 0) { + $sum = 0; + for ($ii = 0; $ii < $n; $ii++) { + $sum += mt_rand(1, $d); + } + + $sum += $bonus; + + return $sum; + } + + + + public function loadOneRandom($classname) { try { return newv($classname, array()) @@ -26,4 +98,5 @@ abstract class PhabricatorTestDataGenerator extends Phobject { return $this->loadOneRandom('PhabricatorUser'); } + } diff --git a/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php b/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php index 215f99402e..866e8b1cb0 100644 --- a/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php +++ b/src/applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php @@ -120,10 +120,30 @@ final class PhabricatorLipsumGenerateWorkflow protected function generate(array $generators) { $viewer = $this->getViewer(); + foreach ($generators as $generator) { + $generator->setViewer($this->getViewer()); + } + while (true) { $generator = $generators[array_rand($generators)]; - $object = $generator->generateObject(); + try { + $object = $generator->generateObject(); + } catch (Exception $ex) { + echo tsprintf( + "** %s ** %s\n", + pht('OOPS'), + pht( + 'Generator ("%s") was unable to generate an object.', + $generator->getGeneratorName())); + + echo tsprintf( + "%B\n", + $ex->getMessage()); + + continue; + } + $object_phid = $object->getPHID(); $handles = $viewer->loadHandles(array($object_phid)); diff --git a/src/applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php b/src/applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php index 31ad44f974..2c2e0561cf 100644 --- a/src/applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php +++ b/src/applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php @@ -76,14 +76,12 @@ final class PhabricatorObjectMailReceiverTestCase } private function buildMail($style) { - - // TODO: Clean up test data generators so that we don't need to guarantee - // the existence of a user. - $this->generateNewTestUser(); - - $task = id(new PhabricatorManiphestTaskTestDataGenerator())->generate(); $user = $this->generateNewTestUser(); + $task = id(new PhabricatorManiphestTaskTestDataGenerator()) + ->setViewer($user) + ->generateObject(); + $is_public = ($style === 'public'); $is_bad_hash = ($style == 'badhash'); $is_bad_user = ($style == 'baduser'); diff --git a/src/applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php b/src/applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php new file mode 100644 index 0000000000..5e78a7d2c0 --- /dev/null +++ b/src/applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php @@ -0,0 +1,75 @@ + array( + '[project]', + '[project] [tion]', + '[action] [project]', + '[action] [project] [tion]', + ), + 'project' => array( + 'Backend', + 'Frontend', + 'Web', + 'Mobile', + 'Tablet', + 'Robot', + 'NUX', + 'Cars', + 'Drones', + 'Experience', + 'Swag', + 'Security', + 'Culture', + 'Revenue', + 'Ion Cannon', + 'Graphics Engine', + 'Drivers', + 'Audio Drivers', + 'Graphics Drivers', + 'Hardware', + 'Data Center', + '[project] [project]', + '[adjective] [project]', + '[adjective] [project]', + ), + 'adjective' => array( + 'Self-Driving', + 'Self-Flying', + 'Self-Immolating', + 'Secure', + 'Insecure', + 'Somewhat-Secure', + 'Orbital', + 'Next-Generation', + ), + 'tion' => array( + 'Automation', + 'Optimization', + 'Performance', + 'Improvement', + 'Growth', + 'Monetization', + ), + 'action' => array( + 'Monetize', + 'Monetize', + 'Triage', + 'Triaging', + 'Automate', + 'Automating', + 'Improve', + 'Improving', + 'Optimize', + 'Optimizing', + 'Accelerate', + 'Accelerating', + ), + ); + } + +} diff --git a/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php b/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php index 8ffa66e331..1962a43f5d 100644 --- a/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php +++ b/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php @@ -3,79 +3,76 @@ final class PhabricatorProjectTestDataGenerator extends PhabricatorTestDataGenerator { - private $xactions = array(); - public function getGeneratorName() { return pht('Projects'); } public function generateObject() { - $title = $this->generateTitle(); - $author = $this->loadPhabrictorUser(); - $author_phid = $author->getPHID(); - $project = PhabricatorProject::initializeNewProject($author) - ->setName($title); + $author = $this->loadRandomUser(); + $project = PhabricatorProject::initializeNewProject($author); - $this->addTransaction( + $xactions = array(); + + $xactions[] = $this->newTransaction( PhabricatorProjectTransaction::TYPE_NAME, - $title); - $project->attachMemberPHIDs( - $this->loadMembersWithAuthor($author_phid)); - $this->addTransaction( + $this->newProjectTitle()); + + $xactions[] = $this->newTransaction( PhabricatorProjectTransaction::TYPE_STATUS, - $this->generateProjectStatus()); - $this->addTransaction( - PhabricatorTransactions::TYPE_VIEW_POLICY, - PhabricatorPolicies::POLICY_PUBLIC); - $this->addTransaction( - PhabricatorTransactions::TYPE_EDIT_POLICY, - PhabricatorPolicies::POLICY_PUBLIC); - $this->addTransaction( - PhabricatorTransactions::TYPE_JOIN_POLICY, - PhabricatorPolicies::POLICY_PUBLIC); + $this->newProjectStatus()); + + // Almost always make the author a member. + $members = array(); + if ($this->roll(1, 20) > 2) { + $members[] = $author->getPHID(); + } + + // Add a few other members. + $size = $this->roll(2, 6, -2); + for ($ii = 0; $ii < $size; $ii++) { + $members[] = $this->loadRandomUser()->getPHID(); + } + + $xactions[] = $this->newTransaction( + PhabricatorTransactions::TYPE_EDGE, + array( + '+' => array_fuse($members), + ), + array( + 'edge:type' => PhabricatorProjectProjectHasMemberEdgeType::EDGECONST, + )); $editor = id(new PhabricatorProjectTransactionEditor()) ->setActor($author) - ->setContentSource(PhabricatorContentSource::newConsoleSource()) + ->setContentSource($this->getLipsumContentSource()) ->setContinueOnNoEffect(true) - ->applyTransactions($project, $this->xactions); + ->applyTransactions($project, $xactions); - return $project->save(); + return $project; } - private function addTransaction($type, $value) { - $this->xactions[] = id(new PhabricatorProjectTransaction()) + private function newTransaction($type, $value, $metadata = array()) { + $xaction = id(new PhabricatorProjectTransaction()) ->setTransactionType($type) ->setNewValue($value); - } - - public function loadMembersWithAuthor($author) { - $members = array($author); - for ($i = 0; $i < rand(10, 20);$i++) { - $members[] = $this->loadPhabrictorUserPHID(); + foreach ($metadata as $key => $value) { + $xaction->setMetadataValue($key, $value); } - return $members; + + return $xaction; } - public function generateTitle() { - return id(new PhutilLipsumContextFreeGrammar()) + public function newProjectTitle() { + return id(new PhabricatorProjectNameContextFreeGrammar()) ->generate(); } - public function generateDescription() { - return id(new PhutilLipsumContextFreeGrammar()) - ->generateSeveral(rand(30, 40)); - } - - public function generateProjectStatus() { - $statuses = array_keys(PhabricatorProjectStatus::getStatusMap()); - // Make sure 4/5th of all generated Projects are active - $random = rand(0, 4); - if ($random != 0) { - return $statuses[0]; + public function newProjectStatus() { + if ($this->roll(1, 20) > 5) { + return PhabricatorProjectStatus::STATUS_ACTIVE; } else { - return $statuses[1]; + return PhabricatorProjectStatus::STATUS_ARCHIVED; } } }