- <?php
- /**
- * Test methods for the P4 Spec Definition class.
- *
- * @copyright 2012 Perforce Software. All rights reserved.
- * @license Please see LICENSE.txt in top-level folder of this distribution.
- * @version <release>/<patch>
- */
-
- namespace P4Test\Spec;
-
- use P4Test\TestCase;
- use P4\Spec\Exception\Exception as SpecException;
-
- class DefinitionTest extends TestCase
- {
- /**
- * Testing get fields.
- */
- public function testGetFields()
- {
- try {
- $specSpec = \P4\Spec\Definition::fetch('spec');
- $fields = $specSpec->getFields();
- } catch (\Exception $e) {
- $this->fail(
- "Unexpected failure fetching spec spec: ". $e->getMessage()
- );
- }
-
- $expected = array (
- 'Fields' =>
- array (
- 'code' => '351',
- 'dataType' => 'wlist',
- 'displayLength' => '0',
- 'fieldType' => 'required',
- 'wordCount' => '5',
- ),
- 'Words' =>
- array (
- 'code' => '352',
- 'dataType' => 'wlist',
- 'displayLength' => '0',
- 'fieldType' => 'optional',
- 'wordCount' => '2',
- ),
- 'Formats' =>
- array (
- 'code' => '353',
- 'dataType' => 'wlist',
- 'displayLength' => '0',
- 'fieldType' => 'optional',
- 'wordCount' => '3',
- ),
- 'Values' =>
- array (
- 'code' => '354',
- 'dataType' => 'wlist',
- 'displayLength' => '0',
- 'fieldType' => 'optional',
- 'wordCount' => '2',
- ),
- 'Presets' =>
- array (
- 'code' => '355',
- 'dataType' => 'wlist',
- 'displayLength' => '0',
- 'fieldType' => 'optional',
- 'wordCount' => '2',
- ),
- 'Comments' =>
- array (
- 'code' => '356',
- 'dataType' => 'text',
- 'displayLength' => '0',
- 'fieldType' => 'optional',
- ),
- );
-
- $this->assertSame($expected, $fields, "Expected spec fields");
- }
-
- /**
- * Testing get comments.
- */
- public function testGetComments()
- {
- try {
- $specSpec = \P4\Spec\Definition::fetch('spec');
- } catch (\Exception $e) {
- $this->fail(
- "Unexpected failure fetching spec spec: ". $e->getMessage()
- );
- }
-
- $expected = <<<EOE
- # A Perforce Spec Specification.
- #
- # Updating this form can be dangerous!
- # To update the job spec, see 'p4 help jobspec' for proper directions.
- # Otherwise, see 'p4 help spec'.
-
- EOE;
-
- // ensure unix-style line endings are used on Windows
- $expected = str_replace("\r\n", "\n", $expected);
-
- $this->assertSame($expected, $specSpec->getComments(), "Expected comments");
-
- // Clear cache and try again; verifies populating on getComments works
- try {
- $specSpec->clearCache();
- } catch (\Exception $e) {
- $this->fail(
- "Unexpected failure clearing spec spec cache: ". $e->getMessage()
- );
- }
- $this->assertSame($expected, $specSpec->getComments(), "Expected comments, after clear");
- }
-
- /**
- * Test setting the comments
- */
- public function testSetComments()
- {
- $tests = array(
- array(
- 'label' => __LINE__ . ' Empty String',
- 'text' => '',
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' string with hash',
- 'text' => '# test12312test',
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' multiline string with hashes',
- 'text' => "# test line 1\n# test line2\n# test line 3!\n",
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' empty multiline string',
- 'text' => "\n\n",
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' integer',
- 'text' => 10,
- 'error' => "Comments must be a string."
- ),
- array(
- 'label' => __LINE__ . ' float',
- 'text' => 10.1,
- 'error' => "Comments must be a string."
- ),
- array(
- 'label' => __LINE__ . ' bool',
- 'text' => true,
- 'error' => "Comments must be a string."
- ),
- array(
- 'label' => __LINE__ . ' null',
- 'text' => null,
- 'error' => "Comments must be a string."
- ),
- array(
- 'label' => __LINE__ . ' array',
- 'text' => array('test' => 'value'),
- 'error' => "Comments must be a string."
- ),
- );
-
- foreach ($tests as $test) {
- $label = $test['label'];
-
- $spec = new \P4\Spec\Definition;
-
- try {
- $spec->setComments($test['text']);
-
- if ($test['error']) {
- $this->fail("$label: Unexpected success.");
- }
-
- $this->assertSame($spec->getComments(), $test['text'], "$label: Expected Comment");
- } catch (\InvalidArgumentException $e) {
- if (!$test['error']) {
- $this->fail("$label: Unexpected failure.");
- } else {
- $this->assertSame(
- $test['error'],
- $e->getMessage(),
- "$label Expected Error Message"
- );
- }
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label: Unexpected Exception (" . get_class($e) . '): ' . $e->getMessage()
- );
- }
- }
- }
-
- /**
- * Test setting comments whitespace issues.
- */
- public function testSetCommentsWhitespace()
- {
- $tests = array(
- array(
- 'label' => __LINE__ . ' leading whitespace',
- 'value' => "\n\t\n \n# Test Text\n",
- 'out' => "\n\n\n# Test Text\n"
- ),
- array(
- 'label' => __LINE__ . ' interior whitespace',
- 'value' => "# Start Text\n\t\n \n# Test Text\n",
- 'out' => "# Start Text\n\n\n# Test Text\n"
- ),
- array(
- 'label' => __LINE__ . ' trailing whitespace',
- 'value' => "# Test Text\n\t\n \n\n",
- 'out' => "# Test Text\n"
- ),
- array(
- 'label' => __LINE__ . ' no trailing whitespace',
- 'value' => "# Test Text\n# Line 2",
- 'out' => "# Test Text\n# Line 2\n"
- ),
- array(
- 'label' => __LINE__ . ' populated lines, trailing whitespace',
- 'value' => "# Test Text\t\n# Line 2 \n# Last\n",
- 'out' => "# Test Text\t\n# Line 2 \n# Last\n"
- ),
- );
-
- foreach ($tests as $test) {
- // Use explicit 'out' as expected if present, value otherwise
- $expect = array_key_exists('out', $test) ? $test['out'] : $test['value'];
-
- $jobSpec = \P4\Spec\Definition::fetch('job');
-
- $jobSpec->setComments($test['value']);
- $jobSpec->save();
-
- $this->assertSame(
- $expect,
- $jobSpec->getComments(),
- $test['label'] . " Unexpected comment result"
- );
- }
- }
-
- /**
- * Testing get and set type.
- */
- public function testGetSetType()
- {
- $tests = array(
- array(
- 'label' => __LINE__ . ' Empty String',
- 'type' => '',
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' Alpha numeric string',
- 'type' => 'test232test',
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' pure numeric string',
- 'type' => '12345',
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' Alpha string',
- 'type' => 'test',
- 'error' => false
- ),
- array(
- 'label' => __LINE__ . ' integer',
- 'type' => 10,
- 'error' => "Type must be a string."
- ),
- array(
- 'label' => __LINE__ . ' float',
- 'type' => 10.1,
- 'error' => "Type must be a string."
- ),
- array(
- 'label' => __LINE__ . ' bool',
- 'type' => true,
- 'error' => "Type must be a string."
- ),
- array(
- 'label' => __LINE__ . ' null',
- 'type' => null,
- 'error' => "Type must be a string."
- ),
- array(
- 'label' => __LINE__ . ' array',
- 'type' => array('test' => 'value'),
- 'error' => "Type must be a string."
- ),
- );
-
- foreach ($tests as $test) {
- $label = $test['label'];
-
- $spec = new \P4\Spec\Definition;
-
- try {
- $spec->setType($test['type']);
-
- if ($test['error']) {
- $this->fail("$label: Unexpected success.");
- }
-
- $this->assertSame($spec->getType(), $test['type'], "$label: Expected Type");
- } catch (\InvalidArgumentException $e) {
- if (!$test['error']) {
- $this->fail("$label: Unexpected failure.");
- } else {
- $this->assertSame(
- $test['error'],
- $e->getMessage(),
- "$label Expected Error Message"
- );
- }
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label: Unexpected Exception (" . get_class($e) . '): ' . $e->getMessage()
- );
- }
- }
- }
-
- /**
- * Test getField
- */
- public function testGetSetField()
- {
- $specSpec = \P4\Spec\Definition::fetch('spec');
-
- // Verify get field output matched getFields output
- foreach ($specSpec->getFields() as $name => $field) {
- $this->assertSame(
- $field,
- $specSpec->getField($name),
- "Expected Field ". $name
- );
- }
-
- // Verify bad fields throw.
- $badField = 'ahsdhadsl';
-
- $this->assertFalse($specSpec->hasField($badField), 'Garbage field should not exist');
-
- try {
- $specSpec->getField($badField);
- $this->fail('Unexpected Success getting garbage field');
- } catch (SpecException $e) {
- $this->assertSame(
- "Can't get field '$badField'. Field does not exist.",
- $e->getMessage(),
- 'Expected exception for Garbage field'
- );
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "Unexpected Exception (" . get_class($e) . '): ' . $e->getMessage()
- );
- }
-
- // Verify we can get bad field after adding it
- $newFields = array(
- $badField => array (
- 'code' => '512',
- 'dataType' => 'word',
- 'fieldType' => 'optional',
- )
- );
-
- $specSpec->setFields($newFields);
-
- $this->assertTrue($specSpec->hasField($badField), 'Garbage field should now exist');
-
- $this->assertSame(
- $newFields[$badField],
- $specSpec->getField($badField),
- 'Expected retrieved garbage field to match'
- );
- }
-
- /**
- * Test setting invalid calls to setFields
- */
- public function testSetInvalidFields()
- {
- $tests = array(
- array(
- 'label' => __LINE__ . ' Empty String',
- 'value' => '',
- ),
- array(
- 'label' => __LINE__ . ' Alpha string',
- 'value' => 'test',
- ),
- array(
- 'label' => __LINE__ . ' integer',
- 'value' => 10,
- ),
- array(
- 'label' => __LINE__ . ' float',
- 'value' => 10.1,
- ),
- array(
- 'label' => __LINE__ . ' bool',
- 'value' => true,
- ),
- array(
- 'label' => __LINE__ . ' null',
- 'value' => null,
- ),
- );
-
- foreach ($tests as $test) {
- $label = $test['label'];
-
- $spec = \P4\Spec\Definition::fetch('spec');
-
- try {
- $spec->setFields($test['value']);
-
- $this->fail("$label: Unexpected success.");
- } catch (\InvalidArgumentException $e) {
- $this->assertSame(
- "Fields must be an array.",
- $e->getMessage(),
- "$label Expected Error Message"
- );
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label: Unexpected Exception (" . get_class($e) . '): ' . $e->getMessage()
- );
- }
- }
- }
-
- /**
- * Test required fields
- */
- public function testRequiredFields()
- {
- $requiredFields = array('Fields');
-
- $specSpec = \P4\Spec\Definition::fetch('spec');
-
- foreach ($specSpec->getFields() as $name => $field) {
- if (in_array($name, $requiredFields)) {
- $this->assertTrue(
- $specSpec->isRequiredField($name),
- "Expected $name to be required."
- );
- } else {
- $this->assertFalse(
- $specSpec->isRequiredField($name),
- "Expected $name not to be required."
- );
- }
- }
- }
-
- /**
- * Test read only fields
- */
- public function testReadOnlyFields()
- {
- $specSpec = \P4\Spec\Definition::fetch('spec');
- $newFields = array(
- 'optional' => array (
- 'code' => '512',
- 'dataType' => 'word',
- 'fieldType' => 'optional',
- ),
- 'default' => array (
- 'code' => '512',
- 'dataType' => 'word',
- 'fieldType' => 'default',
- ),
- 'required' => array (
- 'code' => '512',
- 'dataType' => 'word',
- 'fieldType' => 'required',
- ),
- 'once' => array (
- 'code' => '512',
- 'dataType' => 'word',
- 'fieldType' => 'once',
- ),
- 'always' => array (
- 'code' => '512',
- 'dataType' => 'word',
- 'fieldType' => 'always',
- ),
- );
- $readOnlyFields = array('once');
-
- $specSpec->setFields($newFields);
-
- foreach ($specSpec->getFields() as $name => $field) {
- if (in_array($name, $readOnlyFields)) {
- $this->assertTrue(
- $specSpec->isReadOnlyField($name),
- "Expected $name to be read-only."
- );
- } else {
- $this->assertFalse(
- $specSpec->isReadOnlyField($name),
- "Expected $name not to be read-only."
- );
- }
- }
- }
-
- /**
- * Test expansion of defaults
- */
- public function testExpandDefault()
- {
- $defaults = array(
- array(
- 'label' => __LINE__ . ' Empty String',
- 'input' => '',
- ),
- array(
- 'label' => __LINE__ . ' Alpha numeric string',
- 'input' => 'test232test',
- ),
- array(
- 'label' => __LINE__ . ' Alpha string',
- 'input' => 'test',
- ),
- array(
- 'label' => __LINE__ . ' Dollar string',
- 'input' => '$noExpand',
- ),
- array(
- 'label' => __LINE__ . ' Invalid Expansion',
- 'input' => '$users',
- ),
- array(
- 'label' => __LINE__ . ' integer',
- 'input' => 10,
- 'exception' => '\InvalidArgumentException'
- ),
- array(
- 'label' => __LINE__ . ' float',
- 'input' => 10.1,
- 'exception' => '\InvalidArgumentException'
- ),
- array(
- 'label' => __LINE__ . ' bool',
- 'input' => true,
- 'exception' => '\InvalidArgumentException'
- ),
- array(
- 'label' => __LINE__ . ' null',
- 'input' => null,
- 'exception' => '\InvalidArgumentException'
- ),
- array(
- 'label' => __LINE__ . ' array',
- 'input' => array('test' => 'value'),
- 'exception' => '\InvalidArgumentException'
- ),
- array(
- 'label' => __LINE__ . ' User Expansion',
- 'input' => '$user',
- 'out' => \P4\Spec\Definition::getDefaultConnection()->getUser()
- ),
- array(
- 'label' => __LINE__ . ' Blank Expansion',
- 'input' => '$blank',
- 'out' => null
- ),
- );
-
- // Test static, unmodified values
- foreach ($defaults as $test) {
- // ensure that an exception of the expected type if thrown when
- // expanding value of an invalid type
- if (isset($test['exception'])) {
- try {
- \P4\Spec\Definition::expandDefault($test['input']);
- $this->fail("Expected throwing a '" . $test['exception'] . "' exception.");
- } catch (\Exception $e) {
- $this->assertTrue($e instanceof $test['exception']);
- }
- continue;
- }
-
- // If we have an 'out' paramater use it. Otherwise assume input == output
- $expect = array_key_exists('out', $test)?$test['out']:$test['input'];
-
- $this->assertSame(
- $expect,
- \P4\Spec\Definition::expandDefault($test['input']),
- "{$test['label']} expected matching return"
- );
- }
- }
-
- /**
- * Test saving a spec
- */
- public function testSave()
- {
- // Snag the spec spec and add a field
- $jobSpec = \P4\Spec\Definition::fetch('job');
- $fields = $jobSpec->getFields();
- $comments = $jobSpec->getComments();
-
- $fields['NewField'] = array (
- 'code' => '198',
- 'dataType' => 'wlist',
- 'displayLength' => '0',
- 'fieldType' => 'optional',
- 'wordCount' => '4'
- );
- $fields['NewField2'] = array (
- 'code' => '199',
- 'dataType' => 'select',
- 'displayLength' => '12',
- 'fieldType' => 'optional',
- 'order' => '0',
- 'position' => 'L',
- 'options' => array (
- 0 => 'local',
- 1 => 'unix',
- )
- );
-
- $jobSpec->setFields($fields);
- $this->assertSame(
- $fields,
- $jobSpec->getFields(),
- 'Expected instance fields to match'
- );
-
- $comments .= "\n# Testing tweak comments!\n";
- $jobSpec->setComments($comments);
- $this->assertSame(
- $comments,
- $jobSpec->getComments(),
- 'Expected instance comments to match'
- );
-
- // Save our changes
- $jobSpec->save();
-
- // Following save, validate fields/comments twice
- // - Run 1 checks against current instance
- // - Run 2 fetches a fresh instance and re-checks
- for ($i=0; $i<2; $i++) {
- $this->assertSame(
- $comments,
- $jobSpec->getComments(),
- "Expected matching comments (run $i)"
- );
-
- $this->assertSame(
- $fields,
- $jobSpec->getFields(),
- "Expected matching fields array (run $i)"
- );
-
- $this->assertSame(
- $fields['NewField'],
- $jobSpec->getField('NewField'),
- "Expected matching NewField array (run $i)"
- );
-
- $this->assertSame(
- $fields['NewField2'],
- $jobSpec->getField('NewField2'),
- "Expected matching NewField2 array (run $i)"
- );
-
- // Verify a fresh instance reflects updated values
- $jobSpec = \P4\Spec\Definition::fetch('job');
- }
- }
- }