- <?php
- /**
- * Test the perl trigger script.
- *
- * @copyright 2015 Perforce Software. All rights reserved.
- * @license Please see LICENSE.txt in top-level folder of this distribution.
- * @version <release>/<patch>
- */
-
- namespace ModuleTest;
-
- use P4\File\File;
- use P4\Spec\Change;
- use Reviews\Model\Review;
-
- class PerlTriggerTest extends BashTriggerTest
- {
- protected $scriptBasename = 'swarm-trigger.pl';
-
- /**
- * Test exempt files count configurable for strict/enforce triggers (with a change under review).
- */
- public function testExemptFileCountWithReview()
- {
- $this->installTriggers(
- array(
- array('job', 'job', array()),
- array('user', 'user', array()),
- array('userdel', 'user', array()),
- array('group', 'group', array()),
- array('groupdel', 'group', array()),
- array('enforce', '//...', array()),
- array('strict', '//...', array())
- )
- );
-
- // create a change to review
- $change = new Change($this->p4);
- $change->setDescription('test');
-
- // add files
- for ($i = 0; $i < 2; $i++) {
- $file = new File($this->p4);
- $file->setFilespec('//depot/a' . $i)
- ->open(null, 'text')
- ->setLocalContents('abc' . $i);
-
- $change->addFile($file);
- }
- $change->save();
-
- // create a review
- $this->p4->run('shelve', array('-c', $change->getId()));
- $review = Review::createFromChange($change, $this->p4)
- ->save()
- ->updateFromChange($change)
- ->save();
-
- // at the first attempt, modify files and try to submit with no files exempt count set,
- // it should fail
- $change->revert();
- for ($i = 0; $i < 4; $i++) {
- $file = new File($this->p4);
- $file->setFilespec('//depot/a' . $i)
- ->open(null, 'text')
- ->setLocalContents('xyz' . $i);
-
- $change->addFile($file);
- }
- $change->save();
-
- // approve the review (otherwise commit will fail)
- $review->setState(Review::STATE_APPROVED)->save();
-
- // delete shelved files before committing
- $this->p4->run('shelve', array('-d', '-c', $change->getId()));
-
- // commit the modified change and verify the output
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertTrue(isset($e));
-
- // second attempt, set exempt files count (lower than number of files in change)
- // and try again, it should succeed
- unset($e);
- $this->configureScript(array('EXEMPT_FILE_COUNT' => 3));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertFalse(isset($e));
- }
-
- /**
- * Test exempt files count configurable for strict/enforce triggers (with change not under review).
- */
- public function testExemptFileCountWithNoReview()
- {
- $this->installTriggers(
- array(
- array('job', 'job', array()),
- array('user', 'user', array()),
- array('userdel', 'user', array()),
- array('group', 'group', array()),
- array('groupdel', 'group', array()),
- array('enforce', '//...', array()),
- array('strict', '//...', array())
- )
- );
-
- // create a change to submit
- $change = new Change($this->p4);
- $change->setDescription('test');
-
- // add 3 files
- for ($i = 0; $i < 3; $i++) {
- $file = new File($this->p4);
- $file->setFilespec('//depot/a' . $i)
- ->open(null, 'text')
- ->setLocalContents('abc' . $i);
-
- $change->addFile($file);
- }
- $change->save();
-
- // commit the change and verify the output
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertTrue(isset($e));
-
- // second attempt, set exempt files count (lower than number of files in change)
- // and try again, it should succeed
- unset($e);
- $this->configureScript(array('EXEMPT_FILE_COUNT' => 2));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertFalse(isset($e));
- }
-
- /**
- * Test strict/enforce triggers in conjunction with EXEMPT_EXTENSIONS config option (with change under review).
- */
- public function testExemptExtensionsWithReview()
- {
- $this->configureScript();
- $this->installTriggers(
- array(
- array('job', 'job', array()),
- array('user', 'user', array()),
- array('userdel', 'user', array()),
- array('group', 'group', array()),
- array('groupdel', 'group', array()),
- array('enforce', '//...', array()),
- array('strict', '//...', array())
- )
- );
-
- // create a change to review
- $change = new Change($this->p4);
- $change->setDescription('test');
-
- // add files
- for ($i = 0; $i < 3; $i++) {
- $file = new File($this->p4);
- $file->setFilespec('//depot/a' . $i)
- ->open(null, 'text')
- ->setLocalContents('abc' . $i);
-
- $change->addFile($file);
- }
- $change->save();
-
- // create a review
- $this->p4->run('shelve', array('-c', $change->getId()));
- $review = Review::createFromChange($change, $this->p4)
- ->save()
- ->updateFromChange($change)
- ->save();
-
- // at the first attempt, modify files and try to submit with no exempt extensions
- // specified, it should fail
- $change->revert();
- $file1 = new File($this->p4);
- $file1->setFilespec('//depot/foo.ext1')
- ->open(null, 'text')
- ->setLocalContents('abc');
-
- $file2 = new File($this->p4);
- $file2->setFilespec('//depot/bar.ext2')
- ->open(null, 'text')
- ->setLocalContents('xyz');
-
- $change->addFile($file1)->addFile($file2)->save();
-
- // approve the review
- $review->setState(Review::STATE_APPROVED)->save();
-
- // delete shelved files before committing
- $this->p4->run('shelve', array('-d', '-c', $change->getId()));
-
- // commit the modified change and verify the output
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $errorMessage = 'content of this change (1) does not match the content of the associated Swarm review (2)';
- $this->assertTrue(isset($e));
- $this->assertTrue(stripos($e->getMessage(), $errorMessage) !== false);
-
- // second attempt, set exemopt extensions to 'ext1', it still should fail
- unset($e);
- $this->configureScript(array('EXEMPT_EXTENSIONS' => 'ext1'));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertTrue(isset($e));
- $this->assertTrue(stripos($e->getMessage(), $errorMessage) !== false);
-
- // third attempt - verify literal dot appears before the extension
- $file = new File($this->p4);
- $file->setFilespec('//depot/foo-ext1')
- ->open(null, 'text')
- ->setLocalContents('xyz');
- $change->setFiles(array($file))->save();
-
- unset($e);
- $this->configureScript(array('EXEMPT_EXTENSIONS' => 'ext1'));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertTrue(isset($e));
- $this->assertTrue(stripos($e->getMessage(), $errorMessage) !== false);
-
- // fourth attempt, set exempt extensions to 'ext1, ext2, ext3', it should succeed
- $change->setFiles(array($file1, $file2))->save();
-
- unset($e);
- $this->configureScript(array('EXEMPT_EXTENSIONS' => '.EXT1, .ext2,ext3'));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- print $e->getMessage();
- exit;
- }
-
- $this->assertFalse(isset($e));
- }
-
- /**
- * Test strict/enforce triggers in conjunction with EXEMPT_EXTENSIONS config option (with change not under review).
- */
- public function testExemptExtensionsWithNoReview()
- {
- $this->configureScript();
- $this->installTriggers(
- array(
- array('job', 'job', array()),
- array('user', 'user', array()),
- array('userdel', 'user', array()),
- array('group', 'group', array()),
- array('groupdel', 'group', array()),
- array('enforce', '//...', array()),
- array('strict', '//...', array())
- )
- );
-
- // create a change and few files
- $change = new Change($this->p4);
- $change->setDescription('test');
-
- $file1 = new File($this->p4);
- $file1->setFilespec('//depot/foo.ext1')
- ->open(null, 'text')
- ->setLocalContents('abc');
-
- $file2 = new File($this->p4);
- $file2->setFilespec('//depot/bar.ext2')
- ->open(null, 'text')
- ->setLocalContents('xyz');
-
- // at the first attempt, try to submit with no exempt extensions specified, it should fail
- $change->addFile($file1)->addFile($file2)->save();
-
- // commit the change and verify the output
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $errorMessage = 'Cannot find a Swarm review associated with this change (1)';
- $this->assertTrue(isset($e));
- $this->assertTrue(stripos($e->getMessage(), $errorMessage) !== false);
-
- // second attempt, set exempt extensions to 'ext1', it still should fail
- unset($e);
- $this->configureScript(array('EXEMPT_EXTENSIONS' => 'ext1'));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertTrue(isset($e));
- $this->assertTrue(stripos($e->getMessage(), $errorMessage) !== false);
-
- // third attempt - verify literal dot appears before the extension
- $file = new File($this->p4);
- $file->setFilespec('//depot/foo-ext1')
- ->open(null, 'text')
- ->setLocalContents('xyz');
- $change->setFiles(array($file))->save();
-
- unset($e);
- $this->configureScript(array('EXEMPT_EXTENSIONS' => 'ext1'));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- }
-
- $this->assertTrue(isset($e));
- $this->assertTrue(stripos($e->getMessage(), $errorMessage) !== false);
-
- // fourth attempt, set exempt extensions to 'ext1, ext2, ext3', it should succeed
- $change->setFiles(array($file1, $file2))->save();
-
- unset($e);
- $this->configureScript(array('EXEMPT_EXTENSIONS' => '.EXT1, .ext2,ext3'));
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- print $e->getMessage();
- exit;
- }
-
- $this->assertFalse(isset($e));
- }
-
- /**
- * @dataProvider strictTriggerWithKtextFilesProvider
- */
- public function testStrictTriggerWithKtextFiles(array $reviewFiles, array $submitFiles, $shouldFail)
- {
- $this->configureScript();
- $this->installTriggers(
- array(
- array('job', 'job', array()),
- array('user', 'user', array()),
- array('userdel', 'user', array()),
- array('group', 'group', array()),
- array('groupdel', 'group', array()),
- array('enforce', '//...', array()),
- array('strict', '//...', array())
- )
- );
-
- // create a change to review
- $change = new Change($this->p4);
- $change->setDescription('strict test');
-
- // add files as specified
- foreach ($reviewFiles as $fileSpec => $properties) {
- $content = isset($properties['content']) ? $properties['content'] : '';
- $type = isset($properties['type']) ? $properties['type'] : null;
-
- $file = new File($this->p4);
- $file->setFilespec($fileSpec)
- ->open(null, $type)
- ->setLocalContents($content);
-
- $change->addFile($file);
- }
- $change->save();
-
- // create a review from the change
- $this->p4->run('shelve', array('-c', $change->getId()));
- $review = Review::createFromChange($change, $this->p4)
- ->save()
- ->updateFromChange($change)
- ->save();
-
- // modify a change (that is now associated with a review) with files as specified and try to commit it
- $change->revert();
- foreach ($submitFiles as $fileSpec => $properties) {
- $content = isset($properties['content']) ? $properties['content'] : '';
- $type = isset($properties['type']) ? $properties['type'] : null;
-
- $file = new File($this->p4);
- $file->setFilespec($fileSpec)
- ->open(null, $type)
- ->setLocalContents($content);
-
- $change->addFile($file);
- }
- $change->save();
-
- // approve the review (otherwise commit will fail)
- $review->setState(Review::STATE_APPROVED)->save();
-
- // delete shelved files before committing
- $this->p4->run('shelve', array('-d', '-c', $change->getId()));
-
- // commit the modified change and verify the output
- try {
- $change->submit();
- } catch (\P4\Connection\Exception\CommandException $e) {
- // if trigger prevents committing the change, this is the exception class thrown
- // we verify the message later
- }
-
- // verify the output
- if ($shouldFail) {
- $this->assertTrue(isset($e));
- $this->assertTrue(
- strpos(
- $e->getMessage(),
- "The content of this change (1) does not match the content of the associated Swarm review (2)"
- ) !== false
- );
- } else {
- // should it not fail, ensure we didn't catch any exception
- $this->assertFalse(isset($e), "Unexpected trigger behaviour (should not fail).");
- }
- }
-
- protected function getExpectedUsage($help = false)
- {
- $usage = parent::getExpectedUsage();
-
- // perl trigger has a short version of usage unless help output requested
- return $help ? $usage : current(explode("\nThis script is", $usage));
- }
-
- protected function adjustTriggerScript(
- $targetFilename,
- array $configPaths,
- array $verifyLines,
- array $deleteLines,
- $insertAfterLine
- ) {
- // we were called with values for bash trigger script, we need to change some
- // of them here according to the perl trigger script
- $offset = 688;
- $verifyLines = array(
- $offset => 'sub parse_config {',
- $offset + 1 => ' my @candidates = (',
- $offset + 4 => ' "$MY_PATH/swarm-trigger.conf"'
- );
- $deleteLines = array($offset + 2, $offset + 3);
- $insertAfterLine = $offset + 1;
-
- // remove trailing \ from config paths and add punctuation at the end
- $configPaths = array_map(
- function ($path) {
- return rtrim($path, ' \\') . ',';
- },
- $configPaths
- );
-
- return parent::adjustTriggerScript(
- $targetFilename,
- $configPaths,
- $verifyLines,
- $deleteLines,
- $insertAfterLine
- );
- }
- }